81 lines
2.1 KiB
JavaScript
81 lines
2.1 KiB
JavaScript
|
|
/**
|
||
|
|
* 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,
|
||
|
|
};
|
||
|
|
};
|