LoginSignup
6
4

More than 5 years have passed since last update.

JavaScript で a 要素を使用したダウンロードでネットワークエラーが起きた

Last updated at Posted at 2017-02-09

JavaScript で生成(canvasで描画するなど)したファイルなどをダウンロードするときは HTML の a 要素download 属性にファイル名を設定し、その要素をクリックすることでできます。

download-example.js
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を利用します。

canvastoBlob など、何らかの方法で Blob オブジェクトを取得できるなら、その Blob オブジェクトを URL.createObjectURL() メソッドに渡して実行することでオブジェクトURLが得られますが、データがData URI schemeでしか得られないこともあります。

その場合は、Data URI schemeBlob オブジェクトに変換してからオブジェクト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

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4