【问题标题】:Symfony2 - Force file downloadSymfony2 - 强制文件下载
【发布时间】:2012-10-22 11:23:01
【问题描述】:

当用户点击下载链接时,我正在尝试下载文件。

在控制器中:

    $response = new Response();
    $response->headers->set('Content-type', 'application/octect-stream');
    $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
    $response->headers->set('Content-Length', filesize($filename));

    return $response;

这是打开对话框保存文件,但它说文件是 0 字节。 并将其更改为:

        $response = new Response();
        $response->headers->set('Content-type', 'application/octect-stream');
        $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
        $response->headers->set('Content-Length', filesize($filename));
        $response->headers->set('Content-Transfer-Encoding', 'binary');
        $response->setContent(readfile($filename));

        return $response;

我得到一堆奇怪的字符而不是文件下载对话框。

最后,将“setContent”行切换为:

    $response->setContent(file_get_contents($filename));

它返回一个 PHP 错误:

致命错误:允许的内存大小...

关于如何实现这一点的任何线索? 我以前在 PHP 中做过(没有 MVC),但我不知道通过 Symfony2 做这件事会缺少什么......

也许解决方案是在 PHP.INI 中设置 memory_limit,但我想这不是最佳做法...

【问题讨论】:

    标签: php symfony header download


    【解决方案1】:

    最舒服的解决方案是

    use Symfony\Component\HttpFoundation\BinaryFileResponse;
    use Symfony\Component\HttpFoundation\ResponseHeaderBag;
    
    $response = new BinaryFileResponse($file);
    $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
    
    return $response;
    

    【讨论】:

    【解决方案2】:

    我终于在没有 X-SendFile 的情况下解决了这个问题(这可能是最佳实践)。无论如何,对于那些无法让 X-Sendfile apache 模块工作(共享主机)的人,这里有一个解决方案:

    // Generate response
    $response = new Response();
    
    // Set headers
    $response->headers->set('Cache-Control', 'private');
    $response->headers->set('Content-type', mime_content_type($filename));
    $response->headers->set('Content-Disposition', 'attachment; filename="' . basename($filename) . '";');
    $response->headers->set('Content-length', filesize($filename));
    
    // Send headers before outputting anything
    $response->sendHeaders();
    
    $response->setContent(file_get_contents($filename));
    
    return $response;
    

    【讨论】:

    • 这不适用于 Chrome。看到这个:stackoverflow.com/questions/19834828/…
    • 谢谢。它节省了我的时间。
    • 最后一行是错误的:它将文件长度附加到响应中。 (readfiles将文件内容发送到输出缓冲区,并返回文件长度,也通过响应发送给用户)
    • 我认为您的代码末尾缺少return $response;
    • 见下方“最舒服的解决方案是”
    【解决方案3】:

    您不应该使用 PHP 来下载文件,因为它是 Apache 或 Nginx 服务器的任务。最好的选择是使用 X-Accel-Redirect(在 Nginx 的情况下)/X-Sendfile(在 Apache 的情况下)头文件下载。

    以下操作 sn-p 可以与配置的 Nginx 一起使用以从 Symfony2 下载文件:

    return new Response('', 200, array('X-Accel-Redirect' => $filename));
    

    UPD1: 配置了 mod_xsendfile 的 apache 代码:

    return new Response('', 200, array(
        'X-Sendfile'          => $filename,
        'Content-type'        => 'application/octet-stream',
        'Content-Disposition' => sprintf('attachment; filename="%s"', $filename))
    );
    

    【讨论】:

    • 感谢亚历山大的回复!你知道如何使用 X-Sendfile 进行管理吗?
    • X-Sendfile 是一个典型的标头,其工作方式类似于X-Accel-Redirect。链接答案在这里:stackoverflow.com/questions/80186/…
    【解决方案4】:

    从 Symfony 3.2 开始,您可以使用 file() controller helper,这是创建 BinaryFileResponse 的快捷方式,如上一个答案所述:

    public function fileAction()
    {
        // send the file contents and force the browser to download it
        return $this->file('/path/to/some_file.pdf');
    }
    

    【讨论】:

      【解决方案5】:

      不知道它是否有帮助,但它是 application/octet-stream 而不是 application/octect-stream

      【讨论】:

        【解决方案6】:

        +1 表示亚历山大响应。

        但是如果你不能使用X-Sendfile,你应该使用2.2中添加的BinaryFileResponse:http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files

        在我的项目中,结果是

        $response = new \Symfony\Component\HttpFoundation\BinaryFileResponse($dir .DIRECTORY_SEPARATOR. $zipName);
        
        $d = $response->headers->makeDisposition(
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
            $zipName
           );
        
        $response->headers->set('Content-Disposition', $d);
        
        return $response;
        

        【讨论】:

          【解决方案7】:

          对于那些没有设置标题选项的人:

          download 属性可能会有所帮助,具体取决于您需要支持的浏览器:

          <a href="{file url}" download>

          <a href="{file url}" download="{a different file name}">

          并非所有旧版浏览器都支持此功能。有关浏览器支持,请参阅此页面:

          https://www.w3schools.com/tags/att_a_download.asp

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-19
            • 1970-01-01
            • 1970-01-01
            • 2012-12-31
            • 2013-06-20
            • 2013-01-27
            • 1970-01-01
            相关资源
            最近更新 更多