Laravel 9迁移后response()->download()返回错误文件名file.txt问题
Laravel 9迁移后
response()->download()在内置服务器下文件名异常问题 问题场景
将Laravel应用从7.30(PHP7.3)迁移至9.5(PHP8.2)后,使用response()->download()返回文件时出现以下问题:
- 浏览器接收的文件被命名为
file.txt,但文件内容正常,重命名为test.zip可正常使用 - 仅在
php artisan serve(PHP内置服务器)环境下出现该问题,Apache服务器环境下文件名正常 - 调试确认
Response::sendHeaders()已正确发送包含Content-Disposition: attachment;filename=test.zip的响应头
原代码示例
$headers = [ 'Content-Description' => 'File Transfer', 'Content-Type' => 'application/zip', ]; return response() ->download($result,'test.zip',$headers) ->deleteFileAfterSend(true);
解决方法
方法1:显式指定完整规范的Content-Disposition头
手动构造符合RFC标准的Content-Disposition头,同时将download方法的文件名参数设为null,避免Laravel重复处理头信息:
$headers = [ 'Content-Description' => 'File Transfer', 'Content-Type' => 'application/zip', 'Content-Disposition' => 'attachment; filename="test.zip"', ]; return response() ->download($result, null, $headers) ->deleteFileAfterSend(true);
方法2:使用Storage::download()替代原生响应方法
Laravel的Storage门面在处理文件下载头时逻辑更严谨,可尝试替换原代码:
return Storage::download($result, 'test.zip', [ 'Content-Description' => 'File Transfer', 'Content-Type' => 'application/zip', ])->deleteFileAfterSend(true);
方法3:强制调整响应头顺序(临时测试方案)
若上述方法无效,可尝试强制调整响应头顺序,确保Content-Disposition在Content-Type之后发送:
$response = response() ->download($result,'test.zip',$headers) ->deleteFileAfterSend(true); // 重新设置头顺序 $response->headers->set('Content-Type', 'application/zip'); $response->headers->set('Content-Disposition', 'attachment; filename="test.zip"'); return $response;
原因分析
PHP8.2的内置HTTP服务器在处理响应头时,对Laravel自动生成的头信息解析逻辑与Apache存在差异,可能存在头格式或顺序的识别偏差,导致浏览器无法正确解析文件名。显式指定符合规范的Content-Disposition头可直接规避该问题。
内容的提问来源于stack exchange,提问作者Agung Prihanggoro
相关产品推荐
相关产品推荐

