こんにちは、広野です。
音声ファイルをブラウザからダウンロードさせようとしても、ダウンロードではなくブラウザ上で自動再生されてしまいます。React アプリ画面内にダウンロードボタンを作るときに一筋縄では行かなかったので、成功したコードを紹介します。本記事の対象は音声ファイルですが、BLOB であれば同様に応用できると思います。
環境
前提となる環境は以下の図の通りです。
- 音声ファイルは Amazon S3 にある。
- Amazon S3 には Amazon CloudFront 経由でアクセスする。
- React アプリから音声ファイルには HTTPS でアクセス可能。(少なくとも <audio> タグによる音声再生は問題なし)
やりたかったこと(失敗)
HTML5 の <audio> タグで Amazon S3 上の音声ファイル (MP3) を再生させています。
<audio> タグにより音声コントロールが画面に表示されます。音声は再生できるのですが、ダウンロードは失敗してしまいます。
画像は Windows 10 Edge ブラウザの例です。
できたこと(成功)
仕方ないので、<audio> タグ付属のダウンロード機能はあきらめ、別のボタンをつくりました。
React コード
前提として、WEB パーツは MUI を使用しています。(MUI の説明は省略)
import React from 'react'; import axios from 'axios'; import Button from '@mui/material/Button'; import IconButton from '@mui/material/IconButton'; import DownloadIcon from '@mui/icons-material/Download'; import Tooltip from '@mui/material/Tooltip'; import Blob from 'cross-blob'; import { saveAs } from 'file-saver'; //中略 //ダウンロードボタンクリック時 const handleClickDownload = async (filename) => { const res = await axios.get("https://xxxxx.xxx/xxxxx/" + filename, {responseType:"blob"}); const blob = await new Blob([res.data], {type:"audio/mpeg"}); saveAs(blob, filename); }; //中略 //ボタン部分抜粋 <Tooltip title="Download" placement="top" arrow> <IconButton color="primary" onClick={() => handleClickDownload("xxxxx.mp3")}> <DownloadIcon /> </IconButton> </Tooltip> <Button onClick={handleCloseDialog}>閉じる</Button>
- ダウンロードボタンを押すと、handleClickDownload 関数を呼び出します。引数としてファイル名を渡します。
- handleClickDownload 関数は、ファイル名に文字列を足して URL にし、axios を使ってデータを GET します。
- 取得したデータを BLOB オブジェクトにします。
- BLOB オブジェクトを保存します。
という流れでダウンロードしないとうまくいきませんでした。
BLOB オブジェクトを生成するためのモジュール cross-blob とファイルを保存するためのモジュール file-saver を使っています。
GitHub - eligrey/FileSaver.js: An HTML5 saveAs() FileSaver implementation
An HTML5 saveAs() FileSaver implementation. Contribute to eligrey/FileSaver.js development by creating an account on Git...
GitHub - Richienb/cross-blob: Cross-platform Blob implementation for Node.js and the Web.
Cross-platform Blob implementation for Node.js and the Web. - Richienb/cross-blob
まとめ
いかがでしたでしょうか?
大したことない機能の割に、地味にハマったので書き残しました。
本記事が皆様のお役に立てれば幸いです。