LaravelでAmazon S3からファイルを非同期でダウンロードする方法

はじめに

LaravelでAmazon S3からファイルを非同期でダウンロードする方法をご紹介します。

環境

  • PHP 8.0.16
  • Laravel Framework 9.6.0

PHP

public function fileDownload(Request $request)
{
    $filePath = $request->input('filePath');

    $s3 = Storage::disk('s3');

    if (!$s3->exists($filePath)) {
        // ファイルが存在しない場合の処理(例外を投げるなど)
    }

    // ファイルのMIMEタイプを取得
    $mimeType = $s3->mimeType($filePath);

    // S3から取得したファイルをJSONで送信するためにBase64でエンコード
    $result = base64_encode($s3->get($filePath));

    return [
        'result' =>  $result,
        'type' => $mimeType
    ];
}

ポイントは、S3から取得したファイルをBase64でエンコードしているところでしょうか。
JSONはバイナリデータに対応していないようなので、
バイナリデータのファイルをBase64でエンコードすることで、
JSONでファイルを送信することを実現しています。

JavaScript

$.ajax({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    },
    url: 'sample/url',
    type: 'POST',
    data: {
        filePath: 'sample/file.jpg'
    }
}).then(response => {
    const arrBuffer = base64ToArrayBuffer(response.result); // Base64をArrayBufferに変換
    const mimeType = response.type;
    const blob = new Blob([arrBuffer], {type: mimeType}); // ArrayBufferでBlobオブジェクトを作成
    const link = document.createElement('a');
    link.download = 'file.jpg'; // ファイル名を指定
    link.href = URL.createObjectURL(blob); // オブジェクトURLを作成
    link.click();
    URL.revokeObjectURL(link.href); // オブジェクトURLを解放
}).catch(error => {
    // エラー処理
});

/**
* Base64をArrayBufferに変換
*/
function base64ToArrayBuffer(data) {
    const binaryStr = atob(data); // Base64のデータをデコード
    const binaryLen = binaryStr.length;
    const bytes = new Uint8Array(binaryLen);
    for (let i = 0; i < binaryLen; i++) {
        bytes[i] = binaryStr.charCodeAt(i);
    }
    return bytes;
}

Base64でエンコードされたファイルをデコードしたデータでBlobオブジェクトを作成したところ、
ファイルが破損して正常にファイルをダウンロードすることができませんでした。
そこで、Base64でエンコードされたファイルをデコード、
そして、それをArrayBufferに変換したデータでBlobオブジェクトを作成したところ、
正常にファイルをダウンロードすることができました。


--------------------------
システム開発のご要望・ご相談はこちらから

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です