ブラウザでBase64で受け取ったファイルをダウンロードする
受託開発担当のRyuです。
先日、サーバからBase64で受け取ったPDFをそのままダウンロードしたい場面に出くわしました。
難なく出来るだろうと高をくくっていたのですが、つまづいたのでメモとして残します。
簡単に流れを説明すると、Base64をBlobへと変換し、それをBlob URL Schemeとしてリンクタグに動的に埋め込み、強制的にそれを叩きます。
<script type="text/javascript" src="jquery-3.1.1.min.js"></script>
<script type="text/javascript">
$(function() {
$ajax(~中略~)
.done(function(data, type) {
downloadPdf(data);
});
});
/**
* Base64とMIMEコンテンツタイプからBlobオブジェクトを作成する。
*
* @param base64
*/
function downloadPdf (base64) {
var mime_ctype = "application/pdf";
var blob = toBlob(data, mime_ctype);
if (window.navigator.msSaveBlob) {
// IEやEdgeの場合、Blob URL Schemeへと変換しなくともダウンロードできる
window.navigator.msSaveOrOpenBlob(blob, "file.pdf");
} else {
// BlobをBlob URL Schemeへ変換してリンクタグへ埋め込む
$("#file_dl").prop("href", window.URL.createObjectURL(blob));
// リンクをクリックする
document.getElementById("file_dl").click();
}
}
/**
* Base64とMIMEコンテンツタイプからBlobオブジェクトを作成する。
* 日本語対応。
*
* @param base64
* @param mime_ctype MIMEコンテンツタイプ
* @returns Blob
*/
function toBlob(base64, mime_ctype) {
// 日本語の文字化けに対処するためBOMを作成する。
var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
var bin = atob(base64.replace(/^.*,/, ''));
var buffer = new Uint8Array(bin.length);
for (var i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
// Blobを作成
try {
var blob = new Blob([bom, buffer.buffer], {
type: mime_ctype,
});
} catch (e) {
return false;
}
return blob;
}
</script>
http://amaraimusi.sakura.ne.jp/note_prg/JavaScript/file_binary.html
http://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813
この辺りを参考にさせてもらいました。
なお、ダウンロードではなくブラウザで表示させるだけの場合は、Base64のままData URI schemeを使えば可能なようです。