Symfony Force下载Reponse中断文本文件

时间:2014-11-10 09:22:59

标签: php symfony download response

我已根据以下答案为我的Symfony应用程序创建了一个函数:https://stackoverflow.com/a/13025363/1749653

功能如下:

public function getForceDownloadResponse($file_path, $file_name){
    $file_info = finfo_open(FILEINFO_MIME_TYPE);
    $mine_type = finfo_file($file_info, $file_path.$file_name);
    finfo_close($file_info);

    $response = new Response();
    $response->headers->set('Cache-Control', 'private');
    $response->headers->set('Content-type', $mine_type);
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $file_name . '"');
    $response->headers->set('Content-length', filesize($file_path.$file_name));

    $response->sendHeaders();
    $response->setContent(readfile($file_path.$file_name));

    return $response;
}

这一切都很顺利......直到有人试图用它下载文本文件。 出于某种原因,所有文本文件都以错误的文件名下载。他们都遵循这种模式: Actual_File_Name-,附件 所以,例如:new_text.txt-,附件 等

经过一番调查后,我发现只有一个不整齐的文本文件。不知何故,响应头字段被公开。 二进制文件将输出如下内容:

Cache-Control:private
Connection:close
Content-Disposition:attachment; filename="Jellyfish.jpg"
Content-Length:775702
Content-Type:image/jpeg
Date:Mon, 10 Nov 2014 09:14:41 GMT
Server:Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.5.6

任何文本文件都如下所示:

Cache-Control:private
Cache-Control:private
Connection:Keep-Alive
Content-Disposition:attachment; filename="full.txt"
Content-Disposition:attachment; filename="full.txt"
Content-Length:15
Content-Type:text/plain; charset=UTF-8
Date:Mon, 10 Nov 2014 09:06:00 GMT
Keep-Alive:timeout=5, max=97
Server:Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.5.6

我怀疑无内容行为根据内容标题行为的原因而存在。但我不能为我的生活弄清楚这些是怎么发生的。

所以,如果有人知道更多关于这些是如何创建的,可能会导致他们表现得如此,或者甚至如何彻底解决问题,那么任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

终于明白了。在这里发布以防某人,某处有类似问题并发现它有用:

因此。事实证明,问题在于:

$response-sendHeaders()

对于二进制文件,此行对于使其工作至关重要。文本文件不需要它,实际上会像上面看到的那样破坏。我还没有找到'为什么'它的行为。但解决方案是简单地检查所请求的文件是否是文本文件。 (对.html文件构建异常,但这更多是项目的可选功能/怪癖,因此可以安全地忽略)

这就是现在的功能,它的工作正常:

public function getForceDownloadResponse($file_path, $file_name){
    $file_info = finfo_open(FILEINFO_MIME_TYPE);
    $mime_type = finfo_file($file_info, $file_path.$file_name);
    $text = (substr(finfo_file($file_info, $file_path.$file_name), 0, 4) == 'text') ? 1 : 0;
    finfo_close($file_info);

    $response = new Response();
    $response->headers->set('Cache-Control', 'private');
    $response->headers->set('Content-type', $mime_type);
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $file_name . '"');
    $response->headers->set('Content-length', filesize($file_path.$file_name));

    if(!$text || $mime_type == 'text/html'){
        $response->sendHeaders();
    }

    $response->setContent(readfile($file_path.$file_name));

    return $response;
}

因为我仍然不知道究竟是什么导致了不同的行为,所以它不像我希望的那样安全和可靠,但到目前为止,它的工作做得很好。