我在使用Laravel 4.2时遇到了一些问题我有一些需要用flash播放器播放的文件
public function get($filename)
{
$file = new Symfony'Component'HttpFoundation'File'File(storage_path().DbConfig::get('system.upload_dir').'/'.DbConfig::get('system.upload_music').'/'.$filename);
$response = Response::make(file_get_contents(storage_path().DbConfig::get('system.upload_dir').'/'.DbConfig::get('system.upload_music').'/'.$filename));
$response->header('Content-Type', $file->getMimeType());
$response->header('Content-Length', $file->getSize());
$response->header('Content-Transfer-Encoding', '');
$response->header('Accept-Range', 'bytes');
$response->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
$response->header('Connection', 'Keep-Alive');
return $response;
}
这服务于文件-如果在chrome中打开它会启动chrome的默认播放器和音乐播放,同样的事情是当我用flash播放器启动它。
但是我不能给记录上发条。如果我用apache(而不是Laravel控制器)提供文件,它工作得很好。
如果有人能帮我解决这个问题,我将非常感激。
通过Laravel提供的报头:
HTTP/1.1 200 OK
Date: Thu, 01 Oct 2015 18:43:59 GMT
Server: Apache/2
Cache-Control: must-revalidate, post-check=0, pre-check=0, private
Content-Transfer-Encoding:
Accept-Range: bytes
Connection: Keep-Alive, Keep-Alive
Set-Cookie: laravel_session=eyJ[...]D; expires=Thu, 01-Oct-2015 20:44:00 GMT; Max-Age=7200; path=/; httponly
Vary: Accept-Encoding,User-Agent
Keep-Alive: timeout=2, max=100
Transfer-Encoding: chunked
Content-Type: audio/mpeg
不带Laravel的Headers:
HTTP/1.1 200 OK
Date: Thu, 01 Oct 2015 18:51:16 GMT
Server: Apache/2
Last-Modified: Fri, 13 Mar 2015 04:03:23 GMT
ETag: "ead61-5112394e338c0"
Accept-Ranges: bytes
Content-Length: 961889
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: audio/mpeg
对我来说突出的标题的主要区别是使用Laravel时缺少Content-Length
。我不知道flash播放器是如何工作的,但我敢打赌,它需要知道文件的长度,以便能够寻找(即wind)到任何位置。
但是,您发布的代码显式地设置了该头。搜索了一下,我发现了这个Laravel问题:2079。他们建议使用未记录的Response::stream
发送文件内容,如下所示:
Response::stream(function() use($fileContent) {
echo $fileContent;
}, 200, $headers);
这是StreamedResponse
的Symfony文档。
响应类型更新
您正在提供静态文件,因此使用适当的响应类型是BinaryFileResponse
到Laravel的Response::download($pathToFile, $name, $headers)
。
(顺便说一下,您可以使用第三个参数来设置标题)
更新Content-Length Symfony的Response
类的源代码持有Content-Length
被删除的关键:
/**
* Prepares the Response before it is sent to the client.
*
* This method tweaks the Response to ensure that it is
* compliant with RFC 2616. Most of the changes are based on
* the Request that is "associated" with this Response.
*
* @param Request $request A Request instance
*
* @return Response The current response.
*/
public function prepare(Request $request)
{
$headers = $this->headers;
if ($this->isInformational() || $this->isEmpty()) {
// [snip]
} else {
// [snip]
// Fix Content-Length
if ($headers->has('Transfer-Encoding')) {
$headers->remove('Content-Length');
}
// [snip]
}
// [snip]
}
RFC 2616不允许同时使用Transfer-Encoding
和Content-Length
头,Symfony强制这样做。引言:
4.4消息长度[…]
3。如果存在Content-Length报头字段(第14.13节),则其为octet中的十进制值表示实体长度和transfer-length。绝对不能发送内容长度报头字段如果这两个长度不同(即,如果使用Transfer-Encoding报头字段存在)。如果收到的消息同时带有传输编码报头字段和内容长度报头字段,后者必须忽略。
另外,根据这个SO问题,Content-Transfer-Encoding
只在邮件中使用。否则使用Transfer-Encoding
还有一件事:你在Laravel中使用Accept-Range
而不是在Apache中使用Accept-Ranges
。
最后,尝试不设置任何标头的普通download
响应,看看会得到什么。然后根据需要添加更多的标题