非同期通信でZipファイルをダウンロードさせる方法
非同期通信でZipファイルをダウンロードさせる方法:
axiosでS3からzipをダウンロードして、それをダウンロードさせる場面があったので、良くある感じでコードを書いてみた。
前提として
ファイルのダウンロードは成功するけれど、解凍するとZipの中身が壊れている…
怪しいと思い、拡張子を
フロントエンドだけで完結する対策として、この2つを思いついたので、どっちが良いか試してみる
とりあえずダウンロードはできる。けれど、ファイル名が
ググった結果ここにたどり着く。
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download
セキュリティ考えるとまあそうかなという仕様ですね。
https://developer.mozilla.org/ja/docs/XMLHttpRequest/Sending_and_Receiving_Binary_Data
ArrayBufferを指定して、明示的にバイナリデータを受信するように設定、
または、直接Blobを指定して構築してもらう。
これであとは、ファイルへのリンクをクリックさせるだけ!
これで無事、Zipファイルがダウンロードできました。
背景
axiosでS3からzipをダウンロードして、それをダウンロードさせる場面があったので、良くある感じでコードを書いてみた。前提として
- S3にはバックエンドから発行されるPresigned URLを使う
- バックエンドを通さず、そのURLに直接アクセスする
最初に書いたコード
await { data } = axios.get('....') const blob = new Blob([data], { type: 'application/zip' }) const uri = URL.createObjectURL(blob) const link = document.createElement('a') link.download = 'sample.zip' link.href = uri link.click()
その結果…
ファイルのダウンロードは成功するけれど、解凍するとZipの中身が壊れている…怪しいと思い、拡張子を
.txt
にして開いてみると、バイナリのようなテキストが並んでるので、Zipとして正しく解釈できていない模様。フロントエンドだけで完結する対策として、この2つを思いついたので、どっちが良いか試してみる
- S3 Presigned URL に直接アクセスさせる
- ファイルの変換をうまくやる
動作確認
1. S3 Presigned URLに直接アクセスさせる
const link = document.createElement('a') link.download = 'sample.zip' link.href = '....' link.click()
download
で指定したものとは違う…ググった結果ここにたどり着く。
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download
This attribute only works for same-origin URLs.という訳で、直接S3 Presigned URLにアクセスするとファイル名を制御できない。
セキュリティ考えるとまあそうかなという仕様ですね。
2. ファイルの変換をうまくやる
https://developer.mozilla.org/ja/docs/XMLHttpRequest/Sending_and_Receiving_Binary_DataArrayBufferを指定して、明示的にバイナリデータを受信するように設定、
const { data } = await axios.get('....', { responseType: 'arraybuffer', headers: { Accept: 'application/zip' }, }) const blob = new Blob([data], { type: 'application/zip' })
const { blob: data } = await axios.get('....', { responseType: 'blob', headers: { Accept: 'application/zip' }, })
const uri = URL.createObjectURL(blob) const link = document.createElement('a') link.download = 'sample.zip' link.href = uri link.click()
コメント
コメントを投稿