12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

はじめに

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に設定するソースコードのみ紹介します:point_up_tone1:言語には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エラーです:joy:
下記の設定をS3のアクセス許可のCORS設定でしました。

{
    "AllowedHeaders": [
        "*"
    ],
    "AllowedMethods": [
        "POST"
    ],
    "AllowedOrigins": [
        "http://localhost:3000"
    ]
}

AllowedOriginsにローカル環境のポート番号を設定します。

さいごに

こちらの記事参考になれば幸いです:woman_tone1::point_up_tone1::dizzy:

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?