簡體   English   中英

使用 XMLHttpRequest 提示下載文件

[英]Prompt file download with XMLHttpRequest

我知道 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 (e) {
    var blob = e.currentTarget.response;
    var contentDispo = e.currentTarget.getResponseHeader('Content-Disposition');
    // https://stackoverflow.com/a/23054920/
    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'));
}

更新:自從引入Blob API以來,此答案不再准確。 詳情請參閱史蒂文的回答。


原始答案:

XHR 請求不會觸發文件下載。 我找不到明確的要求,但是XMLHttpRequest上的W3C 文檔也沒有描述對 content-disposition=attachment 響應的任何特殊反應

如果不是 POST 請求,您可以通過window.open()在單獨的選項卡中下載文件。 這里建議使用帶有target=_blank的隱藏表單

 download: function(){ var postData = new FormData(); var xhr = new XMLHttpRequest(); xhr.open('GET', downloadUrl, true); xhr.responseType = 'blob'; xhr.onload = function (e) { var blob = xhr.response; this.saveOrOpenBlob(blob); }.bind(this) xhr.send(postData); } saveOrOpenBlob: function(blob) { var assetRecord = this.getAssetRecord(); var fileName = 'Test.mp4' var tempEl = document.createElement("a"); document.body.appendChild(tempEl); tempEl.style = "display: none"; url = window.URL.createObjectURL(blob); tempEl.href = url; tempEl.download = fileName; tempEl.click(); window.URL.revokeObjectURL(url); },

試試這個它對我有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM