使用 JavaScript 启动文件下载

IT技术 javascript ajax download
2021-01-29 08:19:30

假设我在我的网站上有文件的下载链接。

单击这些链接时,会向服务器发送 AJAX 请求,服务器会返回带有文件位置的 URL。

我想要做的是在响应返回时指示浏览器下载文件。有没有便携的方法来做到这一点?

6个回答

我们这样做:首先添加这个脚本。

<script type="text/javascript">
function populateIframe(id,path) 
{
    var ifrm = document.getElementById(id);
    ifrm.src = "download.php?path="+path;
}
</script>

把它放在你想要下载按钮的地方(这里我们只使用一个链接):

<iframe id="frame1" style="display:none"></iframe>
<a href="javascript:populateIframe('frame1','<?php echo $path; ?>')">download</a>

文件“download.php”(需要放在您的服务器上)仅包含:

<?php 
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=".$_GET['path']);
   readfile($_GET['path']);
?>

因此,当您单击该链接时,隐藏的 iframe 将获取/打开源文件“download.php”。以路径作为获取参数。我们认为这是最好的解决方案!

应该注意的是,该解决方案的 PHP 部分是一个简单的演示,并且可能非常非常不安全。它允许用户下载任何文件,而不仅仅是预定义的文件集。这意味着他们可以下载站点本身的部分源代码,可能包含 API 凭据等。

是什么阻止了用户查看源代码、获取 download.php 的 url 然后浏览到yoursite.com/download.php?path=config.php以尝试获取您的密码?换句话说:拜托,不要这样做。
2021-03-14 08:19:30
javascript 有什么方法可以知道下载进度(或者只是它是否完整)?
2021-03-17 08:19:30
跟进@Grim ...的评论,他绝对是正确的,不要这样做。使 iframe src 直接链接到文件,并使用 .htaccess 设置该特定文件类型的标头信息。
2021-03-20 08:19:30
@Fabio:if (!file_exists($path)) { header("HTTP/1.1 404 Not Found"); exit; }应该可以解决问题
2021-04-07 08:19:30
一些安全的替代方案:1) 根据白名单检查请求的路径,2) 创建一个 id=>filepath 映射并使用 id 代替。
2021-04-09 08:19:30

我创建了一个开源jQuery 文件下载插件带有示例的演示)(GitHub),它也可以帮助您解决问题。它与 iframe 的工作方式非常相似,但有一些很酷的功能,我发现这些功能非常方便:

  • 用户永远不会离开他们启动文件下载的同一页面。此功能对于现代 Web 应用程序变得至关重要
  • 经过测试的跨浏览器支持(包括移动设备!)
  • 它以类似于 jQuery 的 AJAX API 的方式支持 POST 和 GET 请求
  • successCallback 和 failCallback 函数允许您明确说明用户在任一情况下看到的内容
  • 结合 jQuery UI,开发人员可以轻松地向用户显示一个模式,告诉用户正在下载文件,在下载开始后解除模式,甚至以友好的方式通知用户发生了错误。有关此示例,请参见演示。
你好。有没有办法阻止 Internet Explorer 8 阻止下载?Internet Explorer 信息栏要求确认下载,这会导致页面重新加载而无法下载,结果用户必须再次单击下载链接。提前致谢
2021-03-27 08:19:30
这正是我所需要的。谢谢!
2021-03-29 08:19:30

只需window.location.href = new_url从您的 javascript调用,它就会将浏览器重定向到该 URL,因为它是用户在地址栏中键入的

阅读答案 - 包括已接受的答案,我想指出通过 GET 将路径直接传递给 readfile 的安全隐患。

对某些人来说这似乎很明显,但有些人可能只是复制/粘贴此代码:

<?php 
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=".$_GET['path']);
   readfile($_GET['path']);
?>

那么如果我将诸如“/path/to/fileWithSecrets”之类的东西传递给这个脚本会发生什么?给定的脚本会很高兴地发送 webserver-user 可以访问的任何文件。

有关如何防止这种情况的信息,请参阅此讨论:如何确保文件路径在给定的子目录中?

这应该是评论,而不是答案。
2021-03-16 08:19:30
直接链接到 iframe 中的文件并在 htaccess 中设置标题。
2021-04-02 08:19:30

如果这是您自己的服务器应用程序,那么我建议使用以下标头

Content-disposition: attachment; filename=fname.ext

这将强制任何浏览器下载文件,而不是在浏览器窗口中呈现它。