开始使用JavaScript下载文件
假设我在我的网站上有文件的下载链接 单击这些链接时,会向服务器发送一个AJAX请求,服务器返回带有文件位置的URL开始使用JavaScript下载文件,javascript,ajax,download,Javascript,Ajax,Download,假设我在我的网站上有文件的下载链接 单击这些链接时,会向服务器发送一个AJAX请求,服务器返回带有文件位置的URL 我想做的是,当响应返回时,引导浏览器下载文件。有没有一种可移植的方法可以做到这一点?我建议在页面上创建一个不可见的iframe,并将其src设置为您从服务器收到的url-下载将在不重新加载页面的情况下开始 或者,您可以将当前document.location.href设置为接收的url地址。但是,如果请求的文档实际上不存在,用户可能会看到错误。A同意maxnk提到的方法,但是您可能
我想做的是,当响应返回时,引导浏览器下载文件。有没有一种可移植的方法可以做到这一点?我建议在页面上创建一个不可见的iframe,并将其src设置为您从服务器收到的url-下载将在不重新加载页面的情况下开始
或者,您可以将当前document.location.href设置为接收的url地址。但是,如果请求的文档实际上不存在,用户可能会看到错误。A同意maxnk提到的方法,但是您可能需要重新考虑尝试自动强制浏览器下载URL。它可能适用于二进制文件,但对于其他类型的文件(文本、PDF、图像、视频),浏览器可能希望在窗口(或IFRAME)中渲染,而不是保存到磁盘
如果您确实需要通过Ajax调用来获取最终的下载链接,那么使用DHTML将下载链接(来自Ajax响应)动态写入页面怎么样?通过这种方式,用户可以点击它下载(如果是二进制的),或者在浏览器中查看,或者在链接上选择“另存为”保存到磁盘。这是一个额外的点击,但是用户有更多的控制权。我建议
window.open()
打开一个弹出窗口。如果是下载,将没有窗口,您将获得您的文件。如果有404或其他东西,用户将在新窗口中看到它(因此,他们的工作不会受到干扰,但仍然会收到错误消息)。如果这是您自己的服务器应用程序,我建议使用以下标题
Content-disposition: attachment; filename=fname.ext
这将强制任何浏览器下载该文件,而不是在浏览器窗口中呈现该文件。只需从javascript调用
window.location.href=new\u url
,它会将浏览器重定向到用户在地址栏中键入的url,我们这样做:
首先添加这个脚本
<script type="text/javascript">
function populateIframe(id,path)
{
var ifrm = document.getElementById(id);
ifrm.src = "download.php?path="+path;
}
</script>
函数populateFrame(id,路径)
{
var ifrm=document.getElementById(id);
ifrm.src=“download.php?path=“+path;
}
将此放置在需要下载按钮的位置(此处我们仅使用一个链接):
文件“download.php”(需要放在服务器上)只包含:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
?>
因此,当您单击链接时,隐藏的iframe将获取/打开源文件“download.php”。使用路径作为get参数。
我们认为这是最好的解决方案
应该注意的是,这个解决方案的PHP部分是一个简单的演示,可能非常不安全。它允许用户下载任何文件,而不仅仅是预定义的文件集。这意味着他们可以下载网站本身的部分源代码,可能包含API凭据等。我已经创建了一个开源()(),它也可以帮助解决您的问题。它与iframe的工作原理非常相似,但有一些很酷的特性,我发现它们非常方便:
- 用户从不会离开启动文件下载的同一页面。这一特性对于现代web应用程序来说正变得至关重要
- 已测试的跨浏览器支持(包括手机!)
- 它以类似于jQuery的AJAX API的方式支持POST和GET请求
- successCallback和failCallback函数允许您明确用户在这两种情况下看到的内容
- 结合jQuery UI,开发人员可以轻松地显示一个模式,告诉用户正在进行文件下载,在下载开始后解散该模式,甚至友好地通知用户发生了错误。请参阅演示以获取此示例
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
?>
那么,如果我将类似“/path/to/fileWithSecrets”的内容传递给这个脚本,会发生什么呢?
给定的脚本将愉快地发送Web服务器用户有权访问的任何文件
请参阅本讨论以了解如何防止这种情况:当您只需要将浏览器重定向到不同的window.location.href时,为什么要制作服务器端的东西 下面是解析?file=QueryString()并在1秒内将用户重定向到该地址的代码(即使在Android浏览器上也适用于我):
var-urlParams;
(window.onpopstate=函数(){
变量匹配,
pl=/\+/g,//用空格替换加法符号的正则表达式
搜索=/([^&=]+)=?([^&]*)/g,
decode=函数{返回decodeURIComponent(s.replace(pl)(“”);},
query=window.location.search.substring(1);
urlParams={};
while(match=search.exec(查询))
urlParams[decode(匹配[1])]=decode(匹配[2]);
})();
(window.onload=函数(){
var path=urlParams[“文件”];
setTimeout(函数(){document.location.href=path;},1000);
});
如果您的项目中有jQuery,那么一定要删除那些window.onpopstate&window.onload处理程序,并在$(document.ready)(function(){})中执行所有操作 试试这个lib,它比前面描述的所有解决方案都更现代,因为它使用“下载”属性和各种方法的组合来带来最好的体验
在此解释-
似乎是开始用JavaScript下载的理想代码。要绕过投票结果中的安全漏洞,可以将iframe src直接设置为所需的文件(而不是中间php文件),并在.htaccess文件中设置头信息:
<Files *.apk>
ForceType application/force-download
Header set Content-Disposition attachment
Header set Content-Type application/vnd.android.package-archive
Header set Content-Transfer-Encoding binary
</Files>
ForceType应用程序/强制下载
标题集内容处置附件
标题集内容类型应用程序/vnd.android.package
<script type="text/javascript">
var urlParams;
(window.onpopstate = function () {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
urlParams = {};
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
})();
(window.onload = function() {
var path = urlParams["file"];
setTimeout(function() { document.location.href = path; }, 1000);
});
</script>
<Files *.apk>
ForceType application/force-download
Header set Content-Disposition attachment
Header set Content-Type application/vnd.android.package-archive
Header set Content-Transfer-Encoding binary
</Files>
<?php
if(isset($_GET['path'])){
if(in_array($_GET['path'], glob("*/*.*"))){
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
}
}
?>
<iframe id="download" style="display:none"></iframe>
<input type="submit" value="Download" onclick="ChangeSource('document_path');return false;">
<script type="text/javascript">
<!--
function ChangeSource(path){
document.getElementByID('download').src = 'path_to_php?path=' + document_path;
}
-->
</script>