JavaScript で生成(canvas
で描画するなど)したファイルなどをダウンロードするときは HTML の a
要素のdownload
属性にファイル名を設定し、その要素をクリックすることでできます。
const downloader = document.createElement("a");
downloader.download = "ファイル名";
downloader.href = "data:..."; // URL (Data URI scheme や object URLも可能)
downloader.click();
しかし、ファイルのURLを Data URI scheme で指定した場合、しばしばネットワークエラーが起こりダウンロードできないことがあります。
これは、ファイルサイズが大きい時に、Data URIも長くなり、a
要素におけるsrc
属性の文字数が許容範囲を超えたことが原因です。
これを避けるためには、オブジェクト URLを利用します。
canvas
の toBlob
など、何らかの方法で Blob
オブジェクトを取得できるなら、その Blob
オブジェクトを URL.createObjectURL()
メソッドに渡して実行することでオブジェクトURLが得られますが、データがData URI scheme
でしか得られないこともあります。
その場合は、Data URI scheme
を Blob
オブジェクトに変換してからオブジェクトURLを取得します。
// Data URL -> Blob Object convert
// 参考: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
// uri: Base64エンコードされたデータURI, type: ファイルのMIMEタイプ
const base64ToBlob = uri => {
const parse = uri.slice(5).split(/[,;]/);
const binStr = atob(parse.pop());
const l = binStr.length;
const array = new Uint8Array(l);
for (let i = 0; i < l; i++) {
array[i] = binStr.charCodeAt(i);
}
return new Blob([array], {type: parse[0]});
}
上の関数などでできたBlob
オブジェクトをURL.createObjectURL()
でオブジェクトURLに変換し、先述のダウンロードするa
要素に設定すればうまく行くはずです。
また、オブジェクトURLはMDNにもある通り、一時的なものなので、click()
を実行後に開放しましょう。
// blob: Blobオブジェクト
const download = blob => {
const url = URL.createObjectURL(blob);
const downloader = document.createElement("a");
downloader.download = "ファイル名";
downloader.href = url;
downloader.click();
URL.revokeObjectURL(url); // オブジェクトURLを開放
}
参考資料
javascript - Download Canvas as PNG in fabric.js giving network Error - Stack Overflow