/** * Send HTTP response * * @param DispatcherResponseInterface $response * @return boolean */ public function send(DispatcherResponseInterface $response) { $request = $response->getRequest(); if ($response->isStreamable()) { //Explicitly set the Accept Ranges header to bytes to inform client we accept range requests $response->headers->set('Accept-Ranges', 'bytes'); //Set a file etag $response->headers->set('etag', $this->getFileEtag($response)); if ($request->isStreaming()) { if ($response->isSuccess()) { //Default Content-Type Header if (!$response->headers->has('Content-Type')) { $response->headers->set('Content-Type', 'application/octet-stream'); } //Transfer Encoding Headers $response->headers->set('Transfer-Encoding', 'chunked'); //Content Range Headers $offset = $this->getOffset($response); $range = $this->getRange($response); $size = $this->getFileSize($response); $response->setStatus(HttpResponse::PARTIAL_CONTENT); $response->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $offset, $range, $size)); } if ($response->isError()) { /** * A server sending a response with status code 416 (Requested range not satisfiable) SHOULD include a * Content-Range field with a byte-range- resp-spec of "*". The instance-length specifies the current * length of the selected resource. * * @see : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16 */ if ($response->getStatusCode() == HttpResponse::REQUESTED_RANGE_NOT_SATISFIED) { $size = $this->getFileSize($response); $response->headers->set('Content-Range', sprintf('bytes */%s', $size)); } } } return parent::send($response); } }