Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. BinaryFileResponse.php

function BinaryFileResponse::prepare

Overrides Response::prepare

File

vendor/symfony/http-foundation/BinaryFileResponse.php, line 181

Class

BinaryFileResponse
BinaryFileResponse represents an HTTP response delivering a file.

Namespace

Symfony\Component\HttpFoundation

Code

public function prepare(Request $request) : static {
    if ($this->isInformational() || $this->isEmpty()) {
        parent::prepare($request);
        $this->maxlen = 0;
        return $this;
    }
    if (!$this->headers
        ->has('Content-Type')) {
        $this->headers
            ->set('Content-Type', $this->file
            ->getMimeType() ?: 'application/octet-stream');
    }
    parent::prepare($request);
    $this->offset = 0;
    $this->maxlen = -1;
    if ($this->tempFileObject) {
        $fileSize = $this->tempFileObject
            ->fstat()['size'];
    }
    elseif (false === ($fileSize = $this->file
        ->getSize())) {
        return $this;
    }
    $this->headers
        ->remove('Transfer-Encoding');
    $this->headers
        ->set('Content-Length', $fileSize);
    if (!$this->headers
        ->has('Accept-Ranges')) {
        // Only accept ranges on safe HTTP methods
        $this->headers
            ->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none');
    }
    if (self::$trustXSendfileTypeHeader && $request->headers
        ->has('X-Sendfile-Type')) {
        // Use X-Sendfile, do not send any content.
        $type = $request->headers
            ->get('X-Sendfile-Type');
        $path = $this->file
            ->getRealPath();
        // Fall back to scheme://path for stream wrapped locations.
        if (false === $path) {
            $path = $this->file
                ->getPathname();
        }
        if ('x-accel-redirect' === strtolower($type)) {
            // Do X-Accel-Mapping substitutions.
            // @link https://github.com/rack/rack/blob/main/lib/rack/sendfile.rb
            // @link https://mattbrictson.com/blog/accelerated-rails-downloads
            if (!$request->headers
                ->has('X-Accel-Mapping')) {
                throw new \LogicException('The "X-Accel-Mapping" header must be set when "X-Sendfile-Type" is set to "X-Accel-Redirect".');
            }
            $parts = HeaderUtils::split($request->headers
                ->get('X-Accel-Mapping'), ',=');
            foreach ($parts as $part) {
                [
                    $pathPrefix,
                    $location,
                ] = $part;
                if (str_starts_with($path, $pathPrefix)) {
                    $path = $location . substr($path, \strlen($pathPrefix));
                    // Only set X-Accel-Redirect header if a valid URI can be produced
                    // as nginx does not serve arbitrary file paths.
                    $this->headers
                        ->set($type, $path);
                    $this->maxlen = 0;
                    break;
                }
            }
        }
        else {
            $this->headers
                ->set($type, $path);
            $this->maxlen = 0;
        }
    }
    elseif ($request->headers
        ->has('Range') && $request->isMethod('GET')) {
        // Process the range headers.
        if (!$request->headers
            ->has('If-Range') || $this->hasValidIfRangeHeader($request->headers
            ->get('If-Range'))) {
            $range = $request->headers
                ->get('Range');
            if (str_starts_with($range, 'bytes=')) {
                [
                    $start,
                    $end,
                ] = explode('-', substr($range, 6), 2) + [
                    1 => 0,
                ];
                $end = '' === $end ? $fileSize - 1 : (int) $end;
                if ('' === $start) {
                    $start = $fileSize - $end;
                    $end = $fileSize - 1;
                }
                else {
                    $start = (int) $start;
                }
                if ($start <= $end) {
                    $end = min($end, $fileSize - 1);
                    if ($start < 0 || $start > $end) {
                        $this->setStatusCode(416);
                        $this->headers
                            ->set('Content-Range', \sprintf('bytes */%s', $fileSize));
                    }
                    elseif ($end - $start < $fileSize - 1) {
                        $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
                        $this->offset = $start;
                        $this->setStatusCode(206);
                        $this->headers
                            ->set('Content-Range', \sprintf('bytes %s-%s/%s', $start, $end, $fileSize));
                        $this->headers
                            ->set('Content-Length', $end - $start + 1);
                    }
                }
            }
        }
    }
    if ($request->isMethod('HEAD')) {
        $this->maxlen = 0;
    }
    return $this;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal