我想点击按钮时发送“ajax下载请求”,所以我试着这样:
的javascript:
var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();
的download.php:
<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");
readfile("file.txt");
?>
但是没有按预期工作,我该怎么办?提前谢谢
答案 0 :(得分:89)
2015年4月27日更新
来到HTML5场景的是download attribute。在Firefox和Chrome中它是supported,很快就会进入IE11。根据您的需要,您可以使用它而不是AJAX请求(或使用window.location
),只要您要下载的文件与您的网站位于同一来源。
您可以使用some JavaScript来测试是否支持window.location
,如果不支持,则可以使AJAX请求/ download
成为后备,将其切换为window.location
。< / p>
原始回答
您不能让AJAX请求打开下载提示,因为您必须导航到该文件以提示下载。相反,您可以使用成功函数导航到download.php。这将打开下载提示,但不会更改当前页面。
$.ajax({
url: 'download.php',
type: 'POST',
success: function() {
window.location = 'download.php';
}
});
即使这回答了问题,最好只使用window.location
并完全避免AJAX请求。
答案 1 :(得分:38)
你实际上根本不需要ajax。如果您只是将“download.php”设置为按钮上的href,或者,如果它不是链接,则使用:
window.location = 'download.php';
浏览器应识别二进制下载而不加载实际页面,只是将文件作为下载文件提供。
答案 2 :(得分:29)
要让浏览器下载文件,您需要发出以下命令:
function downloadFile(urlToSend) {
var req = new XMLHttpRequest();
req.open("GET", urlToSend, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=fileName;
link.click();
};
req.send();
}
答案 3 :(得分:13)
有可能。您可以从ajax函数内部开始下载,例如,在创建.csv文件之后。
我有一个ajax函数,可以将联系人数据库导出到.csv文件,在完成后,它会自动启动.csv文件下载。所以,在我得到responseText并且一切正常之后,我会像这样重定向浏览器:
window.location="download.php?filename=export.csv";
我的 download.php 文件如下所示:
<?php
$file = $_GET['filename'];
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=".$file."");
header("Content-Transfer-Encoding: binary");
header("Content-Type: binary/octet-stream");
readfile($file);
?>
没有任何页面刷新,文件会自动开始下载。
注意 - 在以下浏览器中进行了测试:
Chrome v37.0.2062.120
Firefox v32.0.1
Opera v12.17
Internet Explorer v11
答案 4 :(得分:12)
跨浏览器解决方案,在Chrome,Firefox,Edge,IE11上测试。
在DOM中,添加隐藏的链接标记:
<a id="target" style="display: none"></a>
然后:
var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = null;
var contentType = req.getResponseHeader("content-type");
// IE/EDGE seems not returning some response header
if (req.getResponseHeader("content-disposition")) {
var contentDisposition = req.getResponseHeader("content-disposition");
fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
} else {
fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
}
if (window.navigator.msSaveOrOpenBlob) {
// Internet Explorer
window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
} else {
var el = document.getElementById("target");
el.href = window.URL.createObjectURL(blob);
el.download = fileName;
el.click();
}
};
req.send();
答案 5 :(得分:3)
我更喜欢location.assign(url);
完整的语法示例:
document.location.assign('https://www.urltodocument.com/document.pdf');
答案 6 :(得分:0)
从标题中解码文件名有点复杂......
var filename = "default.pdf";
var disposition = req.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1)
{
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1])
filename = matches[1].replace(/['"]/g, '');
}
答案 7 :(得分:0)
此解决方案与上面的解决方案并没有太大不同,但是对我来说,它的效果很好,而且我认为它很干净。
我建议对文件服务器端进行base64编码(如果使用的是PHP,则为base64_encode()),然后将base64编码的数据发送给客户端
在客户端上,您可以这样做:
let blob = this.dataURItoBlob(THE_MIME_TYPE + "," + response.file);
let uri = URL.createObjectURL(blob);
let link = document.createElement("a");
link.download = THE_FILE_NAME,
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
此代码将编码后的数据放在链接中,并模拟对链接的点击,然后将其删除。
答案 8 :(得分:0)
您的需求得到满足
window.location('download.php');
但是我认为您需要传递要下载的文件,而不总是下载相同的文件,因此这就是您使用请求的原因,一种选择是创建一个像showfile.php一样简单的php文件,并执行类似< / p>
var myfile = filetodownload.txt
var url = "shofile.php?file=" + myfile ;
ajaxRequest.open("GET", url, true);
showfile.php
<?php
$file = $_GET["file"]
echo $file;
其中file是在请求中通过Get或Post传递的文件名,然后仅在函数中捕获响应
if(ajaxRequest.readyState == 4){
var file = ajaxRequest.responseText;
window.location = 'downfile.php?file=' + file;
}
}
答案 9 :(得分:0)
还有另一种解决方案,可以用ajax下载网页。但是我指的是必须先处理然后下载的页面。
首先,您需要将页面处理与结果下载分开。
1)在ajax调用中仅进行页面计算。
$.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" }, function(data, status) { if (status == "success") { /* 2) In the answer the page that uses the previous calculations is downloaded. For example, this can be a page that prints the results of a table calculated in the ajax call. */ window.location.href = DownloadPage.php+"?ID="+29; } } ); // For example: in the CalculusPage.php if ( !empty($_POST["calculusFunction"]) ) { $ID = $_POST["ID"]; $query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$_POST["data1"]."', '".$_POST["data2"]."') WHERE id = ".$ID; ... } // For example: in the DownloadPage.php $ID = $_GET["ID"]; $sede = "SELECT * FROM ExamplePage WHERE id = ".$ID; ... $filename="Export_Data.xls"; header("Content-Type: application/vnd.ms-excel"); header("Content-Disposition: inline; filename=$filename"); ...
我希望这种解决方案对我来说对许多人都有用。
答案 10 :(得分:0)
对于那些寻求更现代方法的人,可以使用crossprod(newx, newy) / (sqrt(sum(newx^2)) * sqrt(sum(newy^2)))
[,1]
[1,] 0.5991713
。以下示例显示了如何下载电子表格文件。使用以下代码即可轻松完成。
fetch API
我认为,这种方法比其他fetch(url, {
body: JSON.stringify(data),
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
})
.then(response => response.blob())
.then(response => {
const blob = new Blob([response], {type: 'application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "file.xlsx";
document.body.appendChild(a);
a.click();
})
解决方案更容易理解。而且,它的语法与XMLHttpRequest
方法类似,而无需添加任何其他库。
当然,我建议您检查一下要开发的浏览器,因为这种新方法不适用于IE。您可以在以下link上找到完整的浏览器兼容性列表。
重要:在此示例中,我正在向侦听给定jQuery
的服务器发送JSON请求。必须设置此url
,在我的示例中,我假设您知道这一部分。另外,请考虑您的请求正常工作所需的标题。由于我正在发送JSON,因此必须添加url
标头并将其设置为Content-Type
,以使服务器知道它将接收的请求的类型。
答案 11 :(得分:0)
@Joao Marcos解决方案对我有用,但我必须修改代码以使其在IE上工作,如果代码看起来像这样,则在下面
downloadFile(url,filename) {
var that = this;
const extension = url.split('/').pop().split('?')[0].split('.').pop();
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.responseType = "blob";
req.onload = function (event) {
const fileName = `${filename}.${extension}`;
const blob = req.response;
if (window.navigator.msSaveBlob) { // IE
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
URL.revokeObjectURL(link.href);
};
req.send();
},
答案 12 :(得分:0)
这对我有用
var dataObj = {
somekey:"someValue"
}
$.ajax({
method: "POST",
url: "/someController/someMethod",
data: dataObj,
success: function (response) {
const blob = new Blob([response], { type: 'text/csv' });
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "file.csv";
document.body.appendChild(a);
a.click();
}
});