【问题标题】:Download file with Perl on form submit在表单提交时使用 Perl 下载文件
【发布时间】:2015-03-31 20:33:57
【问题描述】:

我正在尝试在提交表单时启动“另存为”对话框。我的表单很简单,我使用Dropzonejs 拖放文件,它看起来是这样的:

<form action="action.epl" class="dropzone" id="dropzone" method="post">
</form>

因此,当用户删除它提交的文件并启动 action.epl 时。在 action.epl 中,我处理文件并将其保存到服务器。然后我试图吐出文件的加密版本。加密已完成,我已将其删除以确保它不是问题的根源,我现在遇到的问题是我无法从服务器下载它。我有以下内容(也在 action.epl 中):

     $fileName = 'file.pdf';
     $filepath= "/server/path/$fileName";

     open (FILE, "<$filepath") or die "can't open : $!";
     @fileholder = <FILE>;
     close FILE;

     print "Content-Type:application/x-downloadn";
     print "Content-Disposition:attachment;filename=$fileName";
     print @fileholder

它在做 /something/ 因为提交时间是没有这个 sn-p 时的 5 倍。我以为我会得到“另存为”对话框,但没有任何反应。 This tutorial 是我获取信息的地方。

编辑,现在我有了:

     $fileName ='file.pdf';
     $filepath = "/server/path/$fileName";

     print "Content-Type:application/x-download\n";
     print "Content-Disposition:attachment;filename=$fileName\n\n";

     open FILE, '<', $filepath or die "can't open: $!";
     print while <FILE>;
     close FILE;

但是,仍然没有对话框。我看到你的文件句柄中有“$”标志。我也试过了。但我认为你不需要那个对吗?

【问题讨论】:

  • 您的 HTTP 标头和正文之间需要一个空行。此外,与其将文件读入数组并打印,不如在阅读时打印:open my $fh, '&lt;', $filepath or die "can't open: $!"; print while &lt;$fh&gt;;。 (请注意,这必须在您打印标题之后进行。还要注意使用词法文件句柄和 open 的 3-arg 形式,它们通常比 fileglobs 和 2-arg 形式更安全。)
  • 另外,每个标题应该在它自己的行上:print "Content-Type: foo\n"; ...
  • 糟糕,s/fileglobs/typeglobs/ 在我的第一条评论中。
  • 我进行了编辑,在标题后添加了新行和一个额外的新行。我也以不同的方式使用 open。
  • 另外,我有“x-downloadn”,我意识到这是教程中的错字。如果只是修复它就可以修复整个事情。

标签: perl filehandle save-as


【解决方案1】:

我看到您解决了教程中的错字。

"Content-Type:application/x-downloadn"

应该是"Content-Type: application/x-download\n",以指定内容的类型为“application/x-download”,并以“\n”结束标题字段的行。

之后,您将了解浏览器如何处理响应。如果您提供Content-Disposition:attachment;filename=$fileName 标头,则表明附件应该是给定的文件名$filename。许多浏览器会查看文件名,并尝试为扩展寻找合适的 MIME 类型。因此,如果您指定 $filename.pdf,那么对于现代浏览器,“如果它看起来像 pdf 并且闻起来像 pdf,那么它就是 pdf”。您不仅是在对 Content-Disposition 的规范说“这是一个 pdf”,而且还提供了他们下载的文件的名称。在大多数情况下,这应该可以防止后备“另存为”行为。

最好的选择是不提供 Content-Disposition。这样,您无需指定任何默认名称来保存文件,因此浏览器没有可窥探的扩展名。不幸的是,一些浏览器只是默认使用脚本的名称,即使扩展名与内容相比是荒谬的。在我日常处理的一些“企业解决方案”中,我得到名为“report.cgi”的 .csv 文件,因为它们使用只有 Internet Explorer 识别的 MIME 类型并且它们不提供内容处置。买家小心。

底线是你不能强迫浏览器从服务器端打开“另存为”,除非你有关于浏览器的信息并且知道如何欺骗它,或者你根本不给它任何东西过去(即使这样,某些浏览器也可能有默认约定)。

通过指定 Content-Disposition 和文件名,您可以提示文件应该是什么,以及它应该保存为什么。另一方面,如果除了 Content-Type 是 'application/x-download' 之外,您没有向浏览器提供任何其他提示,那么您可能会看到“另存为”对话框,但用户会不知道数据是什么内容。这使您受制于浏览器的默认命名约定。这就是我将 .csv 文件作为“report.cgi”获取的方式,即使服务器为 csv 文件提供 MIME 类型(尽管是 IE-only 风格)。

我所做的是使用 perl 的 File::Type 和 mime_type 函数来获取 mime 类型并简单地指定一个名称。如果您使用 mime_type 函数来确定 MIME 类型,并且不指定要返回的文件,那么您会得到一些愚蠢的事情,例如 .xlsx 文件被下载为 zip 文件,或者其他荒谬的事情。

他们获得“另存为”对话框有多重要,因为归根结底,如果文件内容不适合该类型并且他们尝试打开,他们选择的文件类型是无关紧要的acrobat 中的 excel 文件,反之亦然。

在我多年从事服务器端编程的经验中,我一直发现尝试控制客户端是徒劳的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    • 2010-12-16
    • 1970-01-01
    相关资源
    最近更新 更多