Amazon S3 にある音声ファイルを React アプリ経由でダウンロードするボタンをつくる

こんにちは、広野です。

音声ファイルをブラウザからダウンロードさせようとしても、ダウンロードではなくブラウザ上で自動再生されてしまいます。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>
  1. ダウンロードボタンを押すと、handleClickDownload 関数を呼び出します。引数としてファイル名を渡します。
  2. handleClickDownload 関数は、ファイル名に文字列を足して URL にし、axios を使ってデータを GET します。
  3. 取得したデータを BLOB オブジェクトにします。
  4. 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

まとめ

いかがでしたでしょうか?

大したことない機能の割に、地味にハマったので書き残しました。

本記事が皆様のお役に立てれば幸いです。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもフロントエンド開発の方が好きでして、バックエンド構築を簡単にしてくれたAWSには感謝の気持ちの方が強いです。
取得資格:AWS 認定は13資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2024 Japan AWS Top Engineer 受賞
2022 - 2024 AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。

AWSアプリケーション開発クラウドソリューション
シェアする
タイトルとURLをコピーしました