我知道jQuery的ajax方法无法处理下载,我不想添加一个jQuery插件来执行此操作.
我想知道如何使用XMLHttpRequest发送POST数据来下载文件.
这是我尝试过的:
var postData = new FormData(); postData.append('cells', JSON.stringify(output)); var xhr = new XMLHttpRequest(); xhr.open('POST', '/export/', true); xhr.setRequestHeader("X-CSRFToken", csrftoken); xhr.responseType = 'arraybuffer'; xhr.onload = function (e) { console.log(e); console.log(xhr); } xhr.send(postData);
我正在使用Django,该文件似乎成功发送回客户端.在Chrome的网络标签中,我可以在预览标签中看到乱码(我期待).但我想发回一个zip文件,而不是zip文件的文本表示.这是Django的后端:
wrapper = FileWrapper(tmp_file) response = HttpResponse(wrapper, content_type='application/zip') response['Content-Disposition'] = "attachment; filename=export.zip" response['Content-Length'] = tmp_file.tell() return response
我已经搜索了几个小时,但没有找到关于如何使用XMLHttpRequests执行此操作的正确示例.我不想用POST操作创建一个合适的html表单,因为表单数据相当大,并且是动态创建的.
上面的代码有问题吗?我错过了什么?我只是不知道如何实际将数据作为下载发送到客户端.
如果在发送请求之前将XMLHttpRequest.responseType
属性设置为'blob'
,那么当您收到响应时,它将表示为blob.然后,您可以将blob保存到临时文件并导航到该文件.
var postData = new FormData(); postData.append('cells', JSON.stringify(output)); var xhr = new XMLHttpRequest(); xhr.open('POST', '/export/', true); xhr.setRequestHeader('X-CSRFToken', csrftoken); xhr.responseType = 'blob'; xhr.onload = function (this, event) { var blob = this.response; var contentDispo = this.getResponseHeader('Content-Disposition'); // /sf/ask/17360801/ var fileName = contentDispo.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]; saveOrOpenBlob(blob, fileName); } xhr.send(postData);
以下是一个示例实现saveOrOpenBlob
:
function saveOrOpenBlob(blob, fileName) { window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) { fs.root.getFile(fileName, { create: true }, function (fileEntry) { fileEntry.createWriter(function (fileWriter) { fileWriter.addEventListener("writeend", function () { window.location = fileEntry.toURL(); }, false); fileWriter.write(blob, "_blank"); }, function () { }); }, function () { }); }, function () { }); }
如果您不关心浏览器在可查看文件类型时导航到该文件,那么创建一个始终直接保存到文件的方法要简单得多:
function saveBlob(blob, fileName) { var a = document.createElement('a'); a.href = window.URL.createObjectURL(blob); a.download = fileName; a.dispatchEvent(new MouseEvent('click')); }
XHR请求不会触发文件下载.我找不到明确的要求,但XMLHttpRequest上的W3C doc没有描述对内容处理=附件响应的任何特殊反应
如果不是POST请求,您可以通过window.open()在单独的选项卡中下载文件.这里有人建议使用隐藏的表单与目标= _blank
UPD:自从引入Blob API以来,这个答案不再准确.有关详细信息,请参阅史蒂文的答案.