flask、send_fileでバイナリをDLさせる実装

2時間くらいハマったのでメモしておく。

Excelの場合

$.ajax({
    type: "GET",
    url: "/downloadExcelReport/" + customerId + "/" + deliverYmd.split("/").join("-") + "",
    xhrFields    : {responseType : 'blob'},
  }).done(function(data, textStatus, jqXHR ) {
    var blob=new Blob([data], 
        {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64"});
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = "" + Math.random().toString(32).substring(2) + ".xlsx";
    link.click();
  }).fail(function(data) {
    alert("エラー:" + data.statusText);
  }).always(function(data) {
    ;
});

ajaxのオプション xhrFields : {responseType : ‘blob’} がわからなくて。
今も正直わかってない。どうしてgetリクエストする段階で、xhr(XMLHttpRequest)であることを伝えないといけないのか。このオプションがなくてもサーバ側では正常なxlsxファイルを作ることができている。ダウンロードするときにはエクセルだろうとその他のバイナリファイルだろうと同じ扱いだと思うんだけど。ひとまずこれで実装はできたんだが腑に落ちない。

PDFの場合

//1000人分のPDFファイル名をクライアントから伝えて、マージPDFをもらう
$.ajax({
    type: "POST",
    data: JSON.stringify({"data":files}),
    url: "/pdfMergeSeikyusho",
    contentType:'application/json'
}).done(function(data) {
    var blob=new Blob([data], {type: "application/pdf"});
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = "" + Math.random().toString(32).substring(2) + ".pdf";
    link.click();
}).fail(function(data) {
    alert("エラー:" + data.statusText);
}).always(function(data) {
    ;
});

これはPDF用のブロック。だいぶ前に実装したコードで、こっちは標準的なオプションでcontentType: application/json としている。一方でサーバから受け取るときのBlob変換で “application/pdf”を指定している。pdfはこれでOK。

ちなみに、csvの場合

$.ajax({
    type: "GET",
    url: "/getCsvData/" + viewnm + "/"  + nentuki + "/" + groupkb + "/" + tanto + ""
}).done(function(data) {
    let bom  = new Uint8Array([0xEF, 0xBB, 0xBF]);
    var blob=new Blob([bom, data], {type: "text/csv"});//
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = "" + Math.random().toString(32).substring(2) + ".csv";
    link.click();
}).fail(function(data) {
    alert("エラー:" + data.statusText);
}).always(function(data) {
    ;
});

unicodeのためjs側でbom付きblob変換。これでcsvの文字化けを防ぐ。この類は仕事でも散々経験済み。

受け取るファイルの種類ごとにcontent-typeを意識しないといけないのは、httpヘッダーが異なるからというのはわかるけど、ajaxオプション(リクエストフェーズ)でそれが必要なのはどうして。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA