import { S3Client, PutObjectCommand, GetObjectCommand, HeadObjectCommand, } from "@aws-sdk/client-s3"; // S3 설정 (RustFS) - 환경변수에서 로드 const s3Config = { endpoint: process.env.S3_ENDPOINT, accessKey: process.env.S3_ACCESS_KEY, secretKey: process.env.S3_SECRET_KEY, bucket: "minecraft", publicUrl: "https://s3.caadiq.co.kr", }; // S3 클라이언트 생성 const s3Client = new S3Client({ endpoint: s3Config.endpoint, region: "us-east-1", credentials: { accessKeyId: s3Config.accessKey, secretAccessKey: s3Config.secretKey, }, forcePathStyle: true, // RustFS/MinIO용 }); /** * S3(RustFS)에 파일 업로드 */ async function uploadToS3( bucket, key, data, contentType = "application/octet-stream" ) { const command = new PutObjectCommand({ Bucket: bucket, Key: key, Body: data, ContentType: contentType, }); await s3Client.send(command); // 공개 URL 반환 (key는 인코딩) const encodedKey = key .split("/") .map((s) => encodeURIComponent(s)) .join("/"); return `${s3Config.publicUrl}/${bucket}/${encodedKey}`; } /** * S3(RustFS)에서 파일 다운로드 */ async function downloadFromS3(bucket, key) { const command = new GetObjectCommand({ Bucket: bucket, Key: key, }); const response = await s3Client.send(command); // ReadableStream을 Buffer로 변환 const chunks = []; for await (const chunk of response.Body) { chunks.push(chunk); } return Buffer.concat(chunks); } /** * S3(RustFS)에 파일이 존재하는지 확인 */ async function checkS3Exists(bucket, key) { try { const command = new HeadObjectCommand({ Bucket: bucket, Key: key, }); await s3Client.send(command); return true; } catch (err) { if (err.name === "NotFound" || err.$metadata?.httpStatusCode === 404) { return false; } throw err; } } export { s3Config, uploadToS3, downloadFromS3, checkS3Exists };