はじめに
AWS S3の署名付きURLを使用してファイルアップロード処理をする方法について紹介します。
背景としてはAPI Gateway→Lambdaを介してS3にファイルをアップロードする機能を作成していたのですが、API Gatewayでは10MBまでのファイルしか受け付けない仕様となっており10MB以上のファイルをアップロードするケースがでてきたためこの問題を解消する必要がありました。そこで、画面から直接S3にファイルをアップロードするよう、S3の署名付きURLを使うアップロード処理に変更しました。
処理の流れ
1.画面からAPI Gateway→Lambdaを経由して、S3から署名付きURLを取得する。
2.取得したURLを使用していアップロードを実施。
ソースコード
署名付きURL取得処理
API Gatewayの設定は割愛して、Lambdaに設定するソースコードのみ紹介します言語にはNode.jsを採用しています。
// 必要なnodeモジュールを読み込む
const { S3Client, PutObjectCommand } = require('@aws-sdk/client');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
const client = new S3Client({
region: 'ap-northeast-1',
signatuteVersion: 'v4' // 署名付きURLを取得するにはv4の指定が必要
})
exports.handler = async (event, context) => {
const params = {
Bucket: S3のバケット名を指定,
Key: S3のオブジェクトの取得場所を指定
}
const expires = 署名付きURLでのアクセスの許可時間を指定
try {
// 署名付きURLを取得
const url = await getSignedUrl(client, new PutObjectCommand(parmas), {
expires
})
return {
headers: {
'Access-Control-Allow-Origin': '*'
},
body: url
}
} catch(error) {
return {
headers: {
'Access-Control-Allow-Origin': '*'
},
body: null
}
}
}
アップロード処理
フロントの言語にはReact(Next.js)を採用しています。TypeScriptも使用していますが、ここでは割愛しています。
画面から署名付きURL取得処理の呼び出しから、アップロード処理までを紹介します。
const axios from 'axios';
export async function upload( file ) {
// 署名付きURLの取得
const getUrlResponse = await getSignedUrl();
const url = getUrlResponse.body;
// URLが取得できていない場合の処理内容を記載する
if (!url) return;
// S3にファイルをアップロードする
await uploadFile(url,file);
}
// 署名付きURLの取得
export async function getSignedUrl() {
const result = await axios.get('APIGatewayのURL').then((response) => {
return {
body: response.data
}
}).catch((err) => {
return {
body: null
}
})
return result;
}
// ファイルアップロード処理
export async function uploadFile(url,file) {
const result = await axios.put(url, file, {
headers: {
'Content-Type': file.type
}
}).then((response) => {
return {
body: response.data
}
}).catch((err) => {
return {
body: null
}
})
return result;
}
S3側の設定
実装時に悩まされたのが、CORSエラーです
下記の設定をS3のアクセス許可のCORS設定でしました。
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"POST"
],
"AllowedOrigins": [
"http://localhost:3000"
]
}
AllowedOriginsにローカル環境のポート番号を設定します。
さいごに
こちらの記事参考になれば幸いです