在我们的应用程序中,我们需要实现以下场景:
我们的应用程序是基于ajax的应用程序,因此对我们而言,发送ajax请求(像使用jquery.ajax()
函数一样)非常容易和方便。
但是在googilng之后,事实证明只有在使用非ajax POST请求时才可以下载文件(如this popular SO thread中所述)。因此,我们需要实现更丑陋,更复杂的解决方案,该解决方案要求使用嵌套的隐藏字段来构建form
的HTML结构。
有人可以用简单的词来解释为什么不能使用ajax请求来下载文件吗?其背后的机制是什么?
与AJAX无关。当然,您可以使用AJAX下载文件。但是,文件将保留在内存中,即您无法将文件保存到磁盘。这是因为JavaScript无法与磁盘交互。这将是一个严重的安全问题,并且在所有主流浏览器中都被阻止。
这可以使用称为Blob的新HTML5功能来完成。在该功能之上,有一个库FileSaver.js可用作包装器。
这是我两天前问过自己的问题。有一个使用ExtJS编写的客户端项目,服务器端实现在ASP.Net上。我必须将服务器端转换为Java。有一个功能可以下载XML文件,该文件是服务器在客户端发出Ajax请求后生成的。众所周知,在Ajax请求之后不可能仅将文件存储在内存中就下载文件。但是...在原始应用程序浏览器中会显示带有打开,保存和取消下载选项的常规对话框。 ASP.Net某种程度上改变了标准行为...我花了两天时间再次证明-无法按常规方式下载文件...唯一的例外是ASP.Net ...这是ASP.Net代码
public static void WriteFileToResponse(byte[] fileData, string fileName)
{
var response = HttpContext.Current.Response;
var returnFilename = Path.GetFileName(fileName);
var headerValue = String.Format("attachment; filename={0}",
HttpUtility.UrlPathEncode(
String.IsNullOrEmpty(returnFilename)
? "attachment" : returnFilename));
response.AddHeader("content-disposition", headerValue);
response.ContentType = "application/octet-stream";
response.AddHeader("Pragma", "public");
var utf8 = Encoding.UTF8;
response.Charset = utf8.HeaderName;
response.ContentEncoding = utf8;
response.Flush();
response.BinaryWrite(fileData);
response.Flush();
response.Close();
}
此方法从WebMethod调用,而该方法又从ExtJS.Ajax.request调用。那就是魔术。对我来说,我以servlet和隐藏的iframe结尾...
对于那些希望使用更现代方法的人,可以使用fetch API
。以下示例显示如何下载PDF
文件。使用以下代码即可轻松完成。
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/pdf'});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "file.pdf";
document.body.appendChild(a);
a.click();
})
我相信这种方法比其他XMLHttpRequest
解决方案更容易理解。而且,它具有与jQuery
方法类似的语法,而无需添加任何其他库。
当然,我建议您检查要开发的浏览器,因为这种新方法不适用于IE。您可以在以下[链接] [1]上找到完整的浏览器兼容性列表。
重要
:在本示例中,我向服务器侦听给定的url
时发送JSON请求。必须设置此url
,在我的示例中,我假设您知道这一部分。另外,请考虑您的请求正常工作所需的标题。由于我正在发送JSON,因此必须添加Content-Type
标头并将其设置为application/json; charset=utf-8
,以便让服务器知道它将接收的请求的类型。您可以通过在下载页面中使用隐藏的iframe来执行此操作