Lan*_*ngo 7 php laravel laravel-3
我的文件(126 MB大小,.exe)给了我一些问题.
我正在使用标准的laravel下载方法.
我尝试增加内存,但它仍然说我的内存不足,或者我下载了0 KB大小的文件.
该文档没有提到任何有关大文件大小的内容.
我的代码是
ini_set("memory_limit","-1"); // Trying to see if this works
return Response::download($full_path);
Run Code Online (Sandbox Code Playgroud)
我做错了什么?
- 编辑 -
继续Phill Sparks评论,这就是我所拥有的并且它的工作原理.它是Phill的组合加上一些来自php.net的组合.不确定是否有遗失的东西?
public static function big_download($path, $name = null, array $headers = array())
{
if (is_null($name)) $name = basename($path);
// Prepare the headers
$headers = array_merge(array(
'Content-Description' => 'File Transfer',
'Content-Type' => File::mime(File::extension($path)),
'Content-Transfer-Encoding' => 'binary',
'Expires' => 0,
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Pragma' => 'public',
'Content-Length' => File::size($path),
), $headers);
$response = new Response('', 200, $headers);
$response->header('Content-Disposition', $response->disposition($name));
// If there's a session we should save it now
if (Config::get('session.driver') !== '')
{
Session::save();
}
// Below is from http://uk1.php.net/manual/en/function.fpassthru.php comments
session_write_close();
ob_end_clean();
$response->send_headers();
if ($file = fopen($path, 'rb')) {
while(!feof($file) and (connection_status()==0)) {
print(fread($file, 1024*8));
flush();
}
fclose($file);
}
// Finish off, like Laravel would
Event::fire('laravel.done', array($response));
$response->foundation->finish();
exit;
}
Run Code Online (Sandbox Code Playgroud)
Phi*_*rks 14
发生这种情况是因为Response::download()在将文件提供给用户之前将文件加载到内存中.不可否认,这是框架中的一个缺陷,但大多数人并不试图通过框架提供大型文件.
解决方案1 - 将要下载的文件放在公用文件夹中,静态域中或cdn上 - 完全绕过Laravel.
可以理解的是,您可能试图通过登录来限制对下载的访问,在这种情况下,您需要制作自己的下载方法,这样的事情应该有效......
function sendFile($path, $name = null, array $headers = array())
{
if (is_null($name)) $name = basename($path);
// Prepare the headers
$headers = array_merge(array(
'Content-Description' => 'File Transfer',
'Content-Type' => File::mime(File::extension($path)),
'Content-Transfer-Encoding' => 'binary',
'Expires' => 0,
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Pragma' => 'public',
'Content-Length' => File::size($path),
), $headers);
$response = new Response('', 200, $headers);
$response->header('Content-Disposition', $response->disposition($name));
// If there's a session we should save it now
if (Config::get('session.driver') !== '')
{
Session::save();
}
// Send the headers and the file
ob_end_clean();
$response->send_headers();
if ($fp = fread($path, 'rb')) {
while(!feof($fp) and (connection_status()==0)) {
print(fread($fp, 8192));
flush();
}
}
// Finish off, like Laravel would
Event::fire('laravel.done', array($response));
$response->foundation->finish();
exit;
}
Run Code Online (Sandbox Code Playgroud)
此函数是Response :: download()和Laravel 关闭过程的组合.我自己没有机会测试它,我没有安装Laravel 3.如果能为您完成这项工作,请告诉我.
PS:这个脚本唯一不需要处理的是cookie.不幸的是,Response :: cookies()函数受到保护.如果这成为问题,您可以从函数中提取代码并将其放入sendFile方法中.
PPS:有可能是具有输出缓冲的问题; 如果是一个问题,请参阅readfile()示例中的PHP手册,有一个方法可以在那里工作.
购买力平价:由于您使用的二进制文件的工作,你可能要考虑更换readfile()与 fpassthru()
编辑:忽略PPS和PPPS,我更新了代码以使用fread + print代替,因为这似乎更稳定.
您可以像这样使用 Symfony\Component\HttpFoundation\StreamedResponse:
$response = new StreamedResponse(
function() use ($filePath, $fileName) {
// Open output stream
if ($file = fopen($filePath, 'rb')) {
while(!feof($file) and (connection_status()==0)) {
print(fread($file, 1024*8));
flush();
}
fclose($file);
}
},
200,
[
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment; filename="' . $fileName . '"',
]);
return $response;
Run Code Online (Sandbox Code Playgroud)
欲了解更多信息,请查看此