AWS S3とPagesを連携させる方法

このガイドは、EdgeOne Pages を基盤として AWS S3 と Next.js で構築されたファイルアップロードシステムを、すぐにご利用いただけるように解説します。
クイックスタート
EdgeOne Pagesのテンプレートを使用したデプロイは、AWS S3プロジェクトを一から構築し展開する最速の方法です。Pages のテンプレート市場で AWS S3 Batch Uploader テーマテンプレートをすぐに見つけることができます。

AWS S3のアカウントにログインし、個人センター-セキュリティ証明メニューからアクセスキーを探します。キーをEnvironment Variablesにコピーします。CreateボタンPagesをクリックすると、テンプレートを個人のリポジトリに複製して構築することができます。構築完了後、倉庫からコードを複製して開発することができます。
// AWS access key ID
AWS_ACCESS_KEY_ID=your-access-key-id
// AWS secret access key
AWS_SECRET_ACCESS_KEY=your-secret-access-key
// The AWS region to which this client will send requests
AWS_BUCKET_REGION=your-bucket-region
// AWS bucket name
AWS_BUCKET_NAME=your-bucket-nameローカルデバッグです
リポジトリをローカルにクローンする
git clone https://github.com/TencentEdgeOne/pages-templatespages-templatesでexamples/s3-batch-uploaderを探します。
構成鍵です
s3-batch-uploaderプロジェクトルートディレクトリに。env.exampleのような。env.localファイルを作成します。
AWS S3のアカウントにログインし、パーソナルセンター-セキュリティ証明メニューからアクセスキーを探して。env.localにキーをコピペします。
// AWS access key ID
AWS_ACCESS_KEY_ID=your-access-key-id
// AWS secret access key
AWS_SECRET_ACCESS_KEY=your-secret-access-key
// The AWS region to which this client will send requests
AWS_BUCKET_REGION=your-bucket-region
// AWS bucket name
AWS_BUCKET_NAME=your-bucket-name構成格納バケットポリシーです
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowAccessFromSpecificReferers",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::id:root"
},
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::your-bucket-name/*",
"arn:aws:s3:::your-bucket-name"
]
}]
}上記ポリシーをストレージバケットポリシーにコピーすると、ストレージバケット権限設定メニューからストレージバケットポリシーを見つけることができます。
"Principal": {
"AWS": "arn:aws:iam::id:root"
}上記のprincipal.aws値のidをあなたのアカウントのidに置き換えます。
"Resource": [
"arn:aws:s3:::your-bucket-name/*",
"arn:aws:s3:::your-bucket-name"
]上記のResource配列のyou-buck-nameを実際の格納バケット名に置き換えます。
ブラウザからアップロードできるようにCORSを設定します
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]上記の内容をストレージバケットのクロスソースリソース共有(CORS)にコピーすると、ストレージバケット権限設定メニューからクロスソースリソース共有(CORS)を見つけることができます。
Node.js 18.x をインストールします
本プロジェクトは Next.js 14をベースに開発されているため、サポートされる Node.js の最小バージョンは 18.x となります。
プロジェクトを起動する
npm install
npm run devテンプレートは http://localhost:3003 で実行されています
画像または動画のアップロードを選択します。ファイルのアップロードが完了したことが確認できます。
ページアップロードには2つの方法があります。
- 「アップロードボタン」をクリックして、ローカルファイルを選択します。
- ドラッグ&ドロップアップ:画像や動画を指定のエリアに直接ドラッグ&ドロップするだけでアップロードが完了します。
ファイルサイズに応じて最適なアップロード方法を自動的にマッチングします。
- スライスアップロード:大きなファイル(> 50MB)にマルチスレッドを採用し、自動的にファイルブロックを分割し、転送効率を大幅に向上します。
- 事前署名URL:テキスト送信(通常≦50MB)に適しており、一時的に暗号化されたリンクを介して安全で効率的なダイレクトパスを実現します。
コア原理の紹介
自動最適アップロードマッチングの原理
const BUCKET_NAME = process.env.AWS_BUCKET_NAME!
if (fileSize > 50 * 1024 * 1024) {
const createMultipartCommand = new CreateMultipartUploadCommand({
Bucket: BUCKET_NAME,
Key: key,
ContentType: contentType,
})
const multipartResponse = await s3Client.send(createMultipartCommand)
return NextResponse.json({
uploadId: multipartResponse.UploadId,
key,
publicUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_BUCKET_REGION}.amazonaws.com/${key}`,
multipart: true,
})
} else {
// Presigned URL for direct upload
const command = new PutObjectCommand({
Bucket: BUCKET_NAME,
Key: key,
ContentType: contentType,
})
const uploadUrl = await getSignedUrl(s3Client, command, {
expiresIn: 300, // 5 minutes, consistent with other presigned URLs
})
return NextResponse.json({
uploadUrl,
key,
publicUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_BUCKET_REGION}.amazonaws.com/${key}`,
multipart: false,
fields: {}, // Direct presigned URL doesn't need additional fields
})
}プレサインドURLの仕組み
import { NextRequest, NextResponse } from 'next/server'
import { GetObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
import { UPLOAD_CONFIG } from '../../../config/upload'
import { s3Client, BUCKET_NAME } from '../../../lib/s3-client'
/**
* Generate presigned download URL for a single file
*
* @param request - Request object containing the following parameters:
* - key: S3 object key (file path)
* - expiresIn: URL expiration time (seconds), optional, defaults to config value
*
* @returns JSON response containing:
* - presignedUrl: Presigned download URL
* - expiresIn: URL expiration time
* - key: Original file key
*/
export async function POST(request: NextRequest) {
try {
// Parse request parameters: file key and expiration time
const { key, expiresIn = UPLOAD_CONFIG.PRESIGNED_URL_EXPIRES } = await request.json()
// Validate required file key parameter
if (!key) {
return NextResponse.json(
{ error: 'Missing key parameter' },
{ status: 400 }
)
}
// Create S3 GetObject command for generating download URL
const command = new GetObjectCommand({
Bucket: BUCKET_NAME,
Key: key,
})
// Generate presigned URL, allowing temporary access to S3 object
const presignedUrl = await getSignedUrl(s3Client, command, {
expiresIn: expiresIn,
})
// Return presigned URL and related information
return NextResponse.json({
presignedUrl,
expiresIn,
key,
})
} catch (error) {
// Log error and return server error response
console.error('Error generating presigned URL:', error)
return NextResponse.json(
{ error: 'Failed to generate presigned URL' },
{ status: 500 }
)
}
}よくある質問(FAQ)
フォルダをアップロードしてもいいですか?
テンプレートは現在、フォルダの直接アップロードをサポートしていません。
1.フォルダ内のファイルをすべて選択します
2.アップロード領域までバッチドラッグします
3.すべてのファイルを一度にアップロードします
アップロードしたファイルはどこに保存しますか?
ファイルはAWS S3のクラウドストレージサービスに保存され、場所は格納バケットの配置によって決まります。アップロードに成功するとS3 URLを取得し、ファイルにアクセスできます。
アップロードしたファイルはどうやって削除しますか?
現在のテンプレートは、アップロードリストから単一のファイルレコードを削除するだけで、一括削除には対応していません。S3ファイルを一括削除する場合は、管理者に連絡するか、AWSコンソールを利用します。
アップロードが中断した後に再送することは可能ですか?
テンプレートは現在、断点継続転送をサポートしていません。