发起下载的最佳方法?

时间:2020-03-05 18:52:43  来源:igfitidea点击:

在一个基于PHP的网站上,我想在用户填写简短表格后向他们发送下载包。该网站启动的下载应类似于download.com之类的网站,该网站表示"下载将很快开始"。

我知道几种可能的方法,以及浏览器的兼容性(基于快速测试):

1)做一个指向新文件的" window.open"。

- FireFox 3 blocks this.  
 - IE6 blocks this.  
 - IE7 blocks this.

2)创建一个指向新文件的iframe。

- FireFox 3 seems to think this is OK. (Maybe it's because I already accepted it once?)  
 - IE6 blocks this.  
 - IE7 blocks this.

How can I do this so that at least these three browsers will not object?

好处:有没有不需要浏览器条件语句的方法?

(我相信download.com有条件地采用了这两种方法,但我无法使其中任何一种都起作用。)

回应和说明:

Q: "Why not point the current window to the file?"  
A: That might work, but in this particular case, I want to show them some other content while their download starts - for example, "would you like to donate to this project?"

更新:我已经放弃了这种方法。请参阅以下我的答案,以了解原因。

解决方案

回答

如何更改位置以指向新文件? (例如,通过更改window.location)

回答

我通常只有一个PHP脚本,可以使用适当的Content-Type将文件直接输出到浏览器

if(file_exists($filename)) {
    header("Pragma:  public");
    header("Expires:  0");
    header("Cache-Control:  must-revalidate, pre-check=0");
    header("Cache-Control:  private", false);
    header("Content-Type:  " . $content-type);
    header("Content-Disposition:  attachment; filename=\"" . basename($filename) . "\";" );
    header("Content-Transfer-Encoding:  binary");
    header("Content-Length:  " . filesize($filename));

    readfile("$filename");
}else{
    print "ERROR:  the file " . basename($filename) . " could not be downloaded because it did not exist.";
}

唯一的缺点是,由于它设置了HTTP标头,因此必须先调用它,然后再输出任何其他输出。

但是我们可以具有指向PHP下载页面的链接,这将使浏览器弹出一个下载框,而不会弄乱当前页面的内容。

回答

我们还可以执行大多数浏览器支持的元刷新。 Download.com将一个放在noscript标记中。

<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/>

回答

我一直只是制作一个指向该文件的iframe。

<iframe src="/download.exe" frameborder="0" height="0" width="0"><a href="/download.exe">Click here to download.</a></iframe>

回答

关于不将当前窗口指向下载。
以我的经验,我们仍然可以显示"请捐赠"页面,因为下载(只要它们发送正确的标题)实际上并不会更新浏览器窗口。
我这样做是为了在我的一个站点上进行csv导出,而就用户而言,它只是弹出一个安全的文件窗口。
因此,我将建议一个简单的meta-redirect,如Soldarnal所示。

回答

概括地说,我们有2个目标:

  • 开始下载过程
  • 向用户显示带有捐赠选项的页面

为此,我将执行以下操作:

当用户提交表单时,他将显示带有捐赠选项的结果页面,并显示一条文字,说明下载将在5秒钟内开始。在此页的开头部分,我们按Soldarnal所说的那样输入了META代码:
<meta http-equiv =" refresh" content =" 5; url = / download.php?doc = 123.zip>

就这样。

回答

一个陷阱是,如果未正确设置标头,则可能会遇到IE问题(尤其是版本6)。

确保设置正确的Content-Type,但也考虑设置IE的"缓存"选项(至少)以允许缓存。如果该文件是一个文件,则用户可以打开而不是保存文件(例如MS Word文档),因此IE的早期版本需要缓存该文件,因为他们会将"打开"请求传递给适用的应用程序,指向下载的文件在缓存中。

还有一个相关的问题,如果IE6用户的缓存已满,它将无法正确保存文件(因此,当适用的应用程序获得打开它的权柄时,它将抱怨文件已损坏。

我们可能还希望关闭下载的所有gzip动作(对于IE)

IE6 / IE7都存在下载量过大的问题(例如4.x Gigs ...),因为IE甚至没有下载管理器,但有一点需要注意。

最后,如果IE6是从嵌套iframe中启动的,则有时无法很好地处理下载"推送"。我不确定是什么引发了该问题,但是我发现使用IE6可以更轻松地避免这种情况。

回答

更新:我决定放弃这种方法,而只是向用户提供指向实际文件的链接。我的理由是这样的:

我最初尝试由服务器启动的下载被浏览器阻止了。那让我想到:"浏览器是正确的。它怎么知道这是合法的下载?它应该阻止显然不是用户启动的下载。"

我可以用于服务器启动的下载的任何方法也可以由想要发送恶意软件的人使用。因此,仅当用户通过单击链接专门请求文件时,才应进行下载。

我们可以自由地不同意,如果仍然要启动下载,则希望该线程可以完成下载。

回答

i!

@内森:
我决定这样做:让我的" getfile.php"加载所有必要的内容,然后执行

header("Location: ./$path/$filename");

让浏览器本身直接执行文件认为正确的操作。与我一起在Opera中这也可以正常工作。

但是,在不允许直接访问文件的环境中,这将是一个问题,在这种情况下,我们将不得不寻找另一种方式! (感谢Discordia,我的文件是公共PDF!)

最好的问候,Basty

回答

<a href="normaldownload.zip" onclick="use_dhtml_or_ajax_to_display_page()">

如果保存下载,则当前页面不受影响。只要确保下载未在同一窗口中打开(正确的MIME类型或者" Content-Disposition"),我们就可以显示任何内容。

查看更多完整答案