【问题标题】:Securly download file inside browser with correct filename使用正确的文件名在浏览器中安全下载文件
【发布时间】:2010-09-27 18:27:27
【问题描述】:

我正在一个网站上做一些工作,该网站有一个安全区域,用户只有在登录后才能使用该区域。在这个区域有一个页面,其中包含可以下载的 pdf 文档的链接。物理文档位于网站的根目录之外。 pdf 文档的链接如下所示:

index.php?page=secure-area/download&file=protected.pdf

执行以下操作(注意:我知道这是强制下载而不是在浏览器内部打开文件的方式):

// check security, get filename from request, prefix document download directory and check for file existance then...

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
header('Connection: Close');
set_time_limit(0);
readfile($file);

这很好用,但在 Firefox 3 和 Internet Explorer 7(我没有用任何其他浏览器测试过)不会在浏览器中打开这个文件,它们都显示下载对话框(如预期的那样)。如果我选择打开而不是保存,则会下载文档并在浏览器之外启动 Adob​​e Reader 以呈现文档。

我遇到的问题是在浏览器中下载文件,并且如果保存了正确的默认文件名。

我希望在浏览器中打开该文档。一种方法是使用标题“Content-Disposition: inline;”但这意味着我无法指定文件名(因为似乎被浏览器忽略了)。这样做的问题是当我保存文档时,默认名称是 URL 的名称,而不是 pdf 文档的文件名:

http___example.com_index.php_page=secure_area_download&file=protected.pdf

如何让 Firefox 和 Internet Explorer 在浏览器中打开文档并提供正确的默认文件名来保存?

【问题讨论】:

    标签: security file browser download inline


    【解决方案1】:

    Content-disposition:inline 可以与文件名一起使用。但只有一些浏览器理解并遵循这一点。只有当你自己保存文件名时才能看到效果,你定义的文件名将被使用。

    【讨论】:

      【解决方案2】:

      不,她的意思是在使用“Content-disposition:inline”时无法指定文件名。 'Filename' 仅在使用 'Content-disposition:attachment' 时使用,如在她的第一个示例中。这会导致使用正确的文件名下载文档。然而,这个解决方案试图实现的是一个呈现为内联的文档,当从浏览器下载时使用正确的文件名,而不是脚本名。

      在使用'inline'时,除了url重写之外,还有其他方法可以指定文件名吗?我为呈现文档而编写的页面需要一个数据库 ID,因此我认为重写会更加困难(必须从数据库中查询文件名)。

      【讨论】:

        【解决方案3】:

        我终于想出了解决这个问题的方法。

        虽然 RFC 2183 显示文件名参数可用于 Content-Disposition 标头字段的附件和内联,但似乎浏览器在使用内联时会忽略文件名参数,而是尝试找出文件名应该是什么以 URL 为基础。如果 URL 没有查询字符串,则 URL 中最后一个 / 之后的部分似乎用作文件名。

        我已更改下载受保护 PDF 文档的链接,以使用不包含查询字符串的好 URL,并使用带有 .htaccess 文件的 mod_rewrite 来转换这些好 URL,以使用正确的参数执行正确的脚本:

        旧链接:

        index.php?page=secure-area/download&file=document.pdf
        

        新链接:

        file/secure-area/download/document.pdf 
        

        .htaccess:

        RewriteEngine On
        RewriteRule ^file/secure-area/download/(.*)$ index.php?page=secure-area/download&file=$1 [L]
        

        用于实际发送文件的脚本与我之前使用的脚本相同(注意问题中的示例使用 Content-Disposition: attachment 而不是 Content-Disposition: inline 来演示浏览器在 不内联)。

        // check security, get filename from request, prefix document download directory and check for file existance then...
        header('Content-Type: application/pdf');
        header('Content-Disposition: inline; filename="' . basename($file) . '"');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . filesize($file));
        header('Connection: Close');
        set_time_limit(0);
        readfile($file);
        

        现在 PDF 文档在浏览器中打开,保存时默认文件名是

        document.pdf
        

        而不是

        http___example.com_index.php_page=secure_area_download&file=document.pdf
        

        IE 7 在保存时将文件名中的空格转换为 + 并将单引号转换为 %27(Firefox 不会),我想阻止这种情况发生,但同时我对我所拥有的感到满意得到了。

        【讨论】:

        • 我很想投反对票,因为它没有回答问题,但可能没有令人满意的答案。
        • @mjaggard 实际上它确实回答了我的问题。
        • Internet Explorer 11 仍需要此 hack,而 Chrome 和 Firefox 则不需要(已使用 v47 和 v43 测试)。
        【解决方案4】:

        您通过使用 Content-disposition: attachment 来告诉它这样做。尝试使用 Content-disposition: inline。

        【讨论】:

        • 这并不能解决我遇到的问题。我知道如何让文档在浏览器中打开。我不知道如何在浏览器中打开文件时为其指定文件名,这就是这个问题的意义所在。
        【解决方案5】:

        尝试使用

        Content-Disposition: inline;
        

        【讨论】:

        • 这并不能解决我遇到的问题。我知道如何让文档在浏览器中打开。我不知道如何在浏览器中打开文件时为其指定文件名,这就是这个问题的意义所在。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-27
        • 1970-01-01
        • 2022-06-16
        • 2015-04-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多