Laravel AccessDeniedException,带有文件下载响应

时间:2015-02-04 22:00:58

标签: php symfony laravel-4

在我的Laravel脚本中,我将文本写入使用tmpfile()创建的文件,然后尝试返回文件下载响应,以便用户可以下载该文件。

$file = tmpfile();
fwrite($file, 'Write some text to the file.');
return Response::download(stream_get_meta_data($file)['uri'], 'myFile.txt');

结果是AccessDeniedException说:

The file /tmp/phpJfvGtH could not be accessed

如果我强制不使用Laravel Response类的文件下载响应,它可以正常工作:

header('Content-disposition: attachment; filename=myFile.txt');
header('Content-type: text/plain');
readfile(stream_get_meta_data($file)['uri']);

为什么这样做,但使用Response::download()方法却没有?

我正在使用Laravel Framework version 4.2.16

1 个答案:

答案 0 :(得分:0)

发生这种情况是因为丢失了对文件资源的所有引用。根据{{​​3}}文档:

  

关闭后(例如,通过调用fclose()或tmpfile()返回的文件句柄没有剩余引用)或脚本结束时,文件将自动删除。

在您的情况下,当您将文件路径传递给$file函数而不是处理程序本身时,对文件处理程序download()的唯一引用保留在当前作用域中。

return Response::download(stream_get_meta_data($file)['uri'], 'myFile.txt');

那解决方案呢?

  1. 您可以通过流式传输临时文件的内容(例如Response::stream()
  2. )来自己处理文件响应
  3. 或确保以某种方式不会丢失对文件句柄的引用。我通过将文件处理程序传递给标头选项进行了一些虚拟检查,并且它起作用。 (不知道将来是否会破坏任何内容,因为标头选项并非针对此类情况设计的)

    $file = tmpfile();
    fwrite($file, 'Write some text to the file.');
    return Response::download(stream_get_meta_data($file)['uri'], 'myFile.txt', [
        $file,
    ]);
    
  4. 或者在存储文件夹中创建文件,而不是创建临时文件。考虑一下临时文件的清理机制