mailbox/backend/services/s3Service.js

81 lines
2.1 KiB
JavaScript
Raw Permalink Normal View History

2025-12-16 08:18:15 +09:00
/**
* S3 서비스 (Garage/MinIO 호환)
* 첨부파일 업로드 다운로드
*/
const {
S3Client,
PutObjectCommand,
GetObjectCommand,
} = require("@aws-sdk/client-s3");
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
const crypto = require("crypto");
// S3 클라이언트 설정 (Garage/MinIO 호환 모드)
const s3Client = new S3Client({
region: process.env.AWS_REGION || "garage",
endpoint: process.env.MINIO_ENDPOINT || "http://garage:3900",
forcePathStyle: true,
credentials: {
accessKeyId: process.env.MINIO_ACCESS_KEY,
secretAccessKey: process.env.MINIO_SECRET_KEY,
},
});
const BUCKET_NAME = process.env.MINIO_BUCKET || "emails";
/**
* 첨부파일 업로드
* @param {Buffer} buffer - 파일 내용
* @param {string} filename - 원본 파일명
* @param {string} mimeType - MIME 타입
* @returns {Promise<string>} S3 객체
*/
exports.uploadAttachment = async (buffer, filename, mimeType) => {
// 고유 키 생성: 타임스탬프_랜덤해시_파일명
const key = `${Date.now()}_${crypto
.randomBytes(8)
.toString("hex")}_${filename}`;
await s3Client.send(
new PutObjectCommand({
Bucket: BUCKET_NAME,
Key: key,
Body: buffer,
ContentType: mimeType,
})
);
return key;
};
/**
* 서명된 다운로드 URL 생성 (1시간 유효)
* @param {string} key - S3 객체
* @returns {Promise<string>} 서명된 URL
*/
exports.getAttachmentUrl = async (key) => {
const command = new GetObjectCommand({
Bucket: BUCKET_NAME,
Key: key,
});
return getSignedUrl(s3Client, command, { expiresIn: 3600 });
};
/**
* 객체 스트림 가져오기 (직접 다운로드용)
* @param {string} key - S3 객체
* @returns {Promise<{stream: ReadableStream, contentType: string, contentLength: number}>}
*/
exports.getObjectStream = async (key) => {
const command = new GetObjectCommand({
Bucket: BUCKET_NAME,
Key: key,
});
const response = await s3Client.send(command);
return {
stream: response.Body,
contentType: response.ContentType,
contentLength: response.ContentLength,
};
};