XMLHttpRequest によるファイルのダウンロードを促す 質問する

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 フォームを作成したくありません。

上記のコードに何か問題がありますか? 何か見落としているのでしょうか? 実際にデータをダウンロードとしてクライアントに送信する方法がわかりません。

ベストアンサー1

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'));
}

おすすめ記事