Cara Implement File Upload dengan Claude Code
Pelajari cara implement file upload menggunakan Claude Code. Dilengkapi contoh kode praktis dan panduan langkah demi langkah.
implementasiにClaude Codeを使う fileupload機能
fileupload validasi、署名付きURL、プログレスtampilan、gambarリサイズ dll.implementasi項目 多い機能.Claude Code 一括 依頼 こ dan 、セキュア 使いやすいupload機能 efisien pembangunan bisa dilakukan.
署名付きURLによるダイレクトupload
> S3 署名付きURL 使ったfileupload implementasikan.
> server 経由せず、client dari 直接S3 uploadする構成 dengan 。
> fileサイズ 10MB以下、gambar dan PDF み許可して。
serverサイド(署名付きURL発行)
// src/app/api/upload/route.ts
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { NextRequest, NextResponse } from 'next/server';
import { nanoid } from 'nanoid';
const s3 = new S3Client({ region: 'us-east-1' });
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
const MAX_SIZE = 10 * 1024 * 1024; // 10MB
export async function POST(req: NextRequest) {
const { fileName, fileType, fileSize } = await req.json();
// validasi
if (!ALLOWED_TYPES.includes(fileType)) {
return NextResponse.json(
{ error: '許可されてい tidakfile形式 す' },
{ status: 400 }
);
}
if (fileSize > MAX_SIZE) {
return NextResponse.json(
{ error: 'fileサイズ 10MB以下 ください' },
{ status: 400 }
);
}
const ext = fileName.split('.').pop();
const key = `uploads/${nanoid()}.${ext}`;
const command = new PutObjectCommand({
Bucket: process.env.S3_BUCKET!,
Key: key,
ContentType: fileType,
ContentLength: fileSize,
});
const signedUrl = await getSignedUrl(s3, command, { expiresIn: 300 });
return NextResponse.json({
uploadUrl: signedUrl,
fileUrl: `https://${process.env.S3_BUCKET}.s3.us-east-1.amazonaws.com/${key}`,
key,
});
}
clientサイド(プログレス付きupload)
import { useState, useCallback } from 'react';
interface UploadState {
progress: number;
uploading: boolean;
error: string | null;
fileUrl: string | null;
}
export function useFileUpload() {
const [state, setState] = useState<UploadState>({
progress: 0,
uploading: false,
error: null,
fileUrl: null,
});
const upload = useCallback(async (file: File) => {
setState({ progress: 0, uploading: true, error: null, fileUrl: null });
try {
// 1. 署名付きURL pengambilan
const res = await fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
fileName: file.name,
fileType: file.type,
fileSize: file.size,
}),
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(error);
}
const { uploadUrl, fileUrl } = await res.json();
// 2. S3 直接upload(プログレス付き)
await new Promise<void>((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
setState(prev => ({ ...prev, progress: Math.round((e.loaded / e.total) * 100) }));
}
});
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) resolve();
else reject(new Error('Upload failed'));
});
xhr.addEventListener('error', () => reject(new Error('Network error')));
xhr.open('PUT', uploadUrl);
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
});
setState({ progress: 100, uploading: false, error: null, fileUrl });
return fileUrl;
} catch (err) {
setState(prev => ({
...prev,
uploading: false,
error: (err as Error).message,
}));
throw err;
}
}, []);
return { ...state, upload };
}
uploadkomponen
function FileUploader() {
const { progress, uploading, error, fileUrl, upload } = useFileUpload();
const [dragOver, setDragOver] = useState(false);
const handleDrop = useCallback(async (e: React.DragEvent) => {
e.preventDefault();
setDragOver(false);
const file = e.dataTransfer.files[0];
if (file) await upload(file);
}, [upload]);
const handleFileSelect = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) await upload(file);
}, [upload]);
return (
<div>
<div
onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
onDragLeave={() => setDragOver(false)}
onDrop={handleDrop}
className={`border-2 border-dashed rounded-lg p-8 text-center transition-colors
${dragOver ? 'border-blue-500 bg-blue-50' : 'border-gray-300'}
${uploading ? 'pointer-events-none opacity-50' : 'cursor-pointer'}`}
>
<p className="text-gray-600">
ファイルをドラッグ&ドロップ、またはクリックして選択
</p>
<p className="mt-1 text-sm text-gray-400">
JPEG, PNG, WebP, PDF(10MB以下)
</p>
<input
type="file"
accept="image/jpeg,image/png,image/webp,application/pdf"
onChange={handleFileSelect}
className="hidden"
id="file-input"
/>
<label htmlFor="file-input" className="mt-4 inline-block cursor-pointer rounded bg-blue-600 px-4 py-2 text-white">
ファイルを選択
</label>
</div>
{uploading && (
<div className="mt-4">
<div className="h-2 rounded-full bg-gray-200">
<div
className="h-full rounded-full bg-blue-600 transition-all"
style={{ width: `${progress}%` }}
/>
</div>
<p className="mt-1 text-sm text-gray-500">{progress}%</p>
</div>
)}
{error && <p className="mt-2 text-sm text-red-600">{error}</p>}
{fileUrl && (
<p className="mt-2 text-sm text-green-600">
アップロード完了
</p>
)}
</div>
);
}
pemrosesan gambarリサイズ
uploadされたgambar Lambda 自動リサイズ pemrosesan juga Claude Code 依頼 bisa dilakukan.
// lambda/resize-image.ts
import { S3Event } from 'aws-lambda';
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import sharp from 'sharp';
const s3 = new S3Client({});
const SIZES = [
{ suffix: 'thumb', width: 200, height: 200 },
{ suffix: 'medium', width: 800 },
{ suffix: 'large', width: 1600 },
];
export async function handler(event: S3Event) {
for (const record of event.Records) {
const bucket = record.s3.bucket.name;
const key = decodeURIComponent(record.s3.object.key);
const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
const buffer = Buffer.from(await Body!.transformToByteArray());
for (const size of SIZES) {
const resized = await sharp(buffer)
.resize(size.width, size.height, { fit: 'cover' })
.webp({ quality: 80 })
.toBuffer();
const resizedKey = key.replace(/\.[^.]+$/, `-${size.suffix}.webp`);
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: resizedKey,
Body: resized,
ContentType: 'image/webp',
}));
}
}
}
Summary
Dengan Claude Code, fileupload機能 署名付きURL、プログレスtampilan、validasi、gambarリサイズま 含めてefisien implementasi bisa dilakukan.セキュリティ 考慮 implementasi 一括 generate きる 強み.AWSintegrasi 詳細 AWSdeploy otomatisasi juga bisa dijadikan referensi.個人proyek pemanfaatan法 個人pengembangan 爆速 metode perkenalan い.
Untuk detail Claude Code, lihat Dokumentasi Resmi Anthropic.
PDF Gratis: Cheatsheet Claude Code dalam 5 Menit
Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.
Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.
Tentang Penulis
Masa
Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.
Artikel Terkait
7 pemeriksaan sebelum menerbitkan artikel Claude Code multibahasa setiap hari
Checklist praktis agar artikel Claude Code multibahasa yang diterbitkan setiap hari tidak kehilangan locale, tidak merusak CTA, dan tidak meninggalkan halaman lama di production.
Apa itu Codex Automations? Membiarkan AI mengurus konten saat kamu tidur
Panduan praktis memakai Codex Automations untuk analytics, artikel, CTA, deploy, dan monetisasi.
Claude Code × GCP Cloud Functions Panduan Lengkap | Pengembangan Serverless Super Cepat
Optimalkan GCP Cloud Functions dengan Claude Code. Implementasikan trigger HTTP/Pub/Sub/Firestore, pengujian lokal, dan otomatisasi deployment dengan contoh kode nyata dari pengalaman Masa.