Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/commission/controller/commission.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,5 @@ export const getCommissionReport = async (req, res, next) => {
} catch (err) {
next(err);
}
};
};

90 changes: 29 additions & 61 deletions src/commission/service/commission.service.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { uploadToS3, deleteFromS3 } from '../../s3.upload.js';
import { CommissionRepository } from "../repository/commission.repository.js";
import { RequestRepository } from "../../request/repository/request.repository.js";
import {
Expand All @@ -17,38 +17,14 @@ import {
} from "../../common/errors/commission.errors.js";

export const CommissionService = {
// 업로드 디렉토리 설정
uploadDir: path.join(process.cwd(), 'uploads', 'request-images'),

/**
* 업로드 디렉토리 생성
* S3 업로드를 위한 multer 설정
*/
ensureUploadDir() {
if (!fs.existsSync(this.uploadDir)) {
fs.mkdirSync(this.uploadDir, { recursive: true });
console.log(`업로드 디렉토리 생성: ${this.uploadDir}`);
}
},

/**
* multer 저장소 설정
*/
storage: multer.diskStorage({
destination: function(req, file, cb) {
const uploadDir = path.join(process.cwd(), 'uploads', 'request-images');
cb(null, uploadDir);
},
filename: function(req, file, cb) {
// 파일명: request_현재시간_랜덤값.확장자
const timestamp = Date.now();
const random = Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
cb(null, `request_${timestamp}_${random}${ext}`);
}
}),
storage: multer.memoryStorage(),

/**
* 파일 필터 (이미지만 허용)
* 파일 필터
*/
fileFilter(req, file, cb) {
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png'];
Expand All @@ -67,72 +43,64 @@ export const CommissionService = {
* multer 인스턴스 생성
*/
getUploadMiddleware() {
// 업로드 디렉토리 확인
this.ensureUploadDir();

return multer({
storage: this.storage,
fileFilter: this.fileFilter,
limits: {
fileSize: 5 * 1024 * 1024 // 5MB 제한
fileSize: 10 * 1024 * 1024
}
}).single('image');
},

/**
* 이미지 업로드 처리
* S3 이미지 업로드 처리
*/
async uploadRequestImage(file) {
try {
// 1. 파일 존재 여부 확인
if (!file) {
throw new ImageUploadFailedError('파일이 업로드되지 않았습니다');
throw new ImageUploadFailedError({ reason: '파일이 업로드되지 않았습니다' });
}

// 2. 파일 크기 추가 검증
if (file.size > 5 * 1024 * 1024) {
this.deleteFile(file.path);
throw new FileSizeExceededError({
maxSize: '5MB',
receivedSize: `${Math.round(file.size / 1024 / 1024 * 100) / 100}MB`
});
// 2. 파일 크기 검증
if (file.size > 10 * 1024 * 1024) {
throw new FileSizeExceededError({ fileSize: file.size });
}

// 3. 파일 확장자 검증
const ext = path.extname(file.originalname).toLowerCase().replace('.', '');
if (!['jpeg', 'jpg', 'png'].includes(ext)) {
throw new UnsupportedImageFormatError({ fileType: file.mimetype });
}

// 3. 파일 URL 생성
const baseUrl = process.env.BASE_URL || 'http://localhost:3000';
const imageUrl = `${baseUrl}/uploads/request-images/${file.filename}`;
// 4. S3 업로드 (requests 폴더에 저장)
const imageUrl = await uploadToS3(file.buffer, 'requests', ext);

// 4. 성공 응답 반환
return {
image_url: imageUrl,
file_size: file.size,
file_type: file.mimetype
};

} catch (error) {
// 오류 발생 시 업로드된 파일 삭제
if (file && file.path) {
this.deleteFile(file.path);
}
throw error;
}
},

/**
* 파일 삭제 헬퍼 메서드
* S3 이미지 삭제
*/
deleteFile(filePath) {
async deleteS3Image(imageUrl) {
try {
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
console.log(`파일 삭제: ${filePath}`);
if (imageUrl && imageUrl.includes('amazonaws.com')) {
await deleteFromS3(imageUrl);
console.log(`S3 이미지 삭제 완료: ${imageUrl}`);
}
} catch (error) {
console.error('파일 삭제 실패:', error);
console.error('S3 이미지 삭제 실패:', error);
}
},


/**
* 커미션 게시글 상세글 조회
*/
Expand Down Expand Up @@ -627,39 +595,39 @@ export const CommissionService = {
// 캐릭터 데이터
CHARACTER_DATA: [
{
image: "https://example.com/character1.png",
image: `https://${process.env.AWS_S3_BUCKET_NAME}.s3.dualstack.${process.env.AWS_REGION}.amazonaws.com/reports/reportType1.png`,
quote: {
title: "커미션계의 VIP",
description: "\"커미션계의 큰 손 등장!\" 덕분에 작가님들의 창작 활동이 풍요로워졌어요."
},
condition: "월 사용 포인트 15만포인트 이상"
},
{
image: "https://example.com/character2.png",
image: `https://${process.env.AWS_S3_BUCKET_NAME}.s3.dualstack.${process.env.AWS_REGION}.amazonaws.com/reports/reportType2.png`,
quote: {
title: "작가 덕후 신청자",
description: "\"이 작가님만큼은 믿고 맡긴다!\" 단골의 미덕을 지닌 당신, 작가님도 감동했을 거예요."
},
condition: "같은 작가에게 3회 이상 신청"
},
{
image: "https://example.com/character3.png",
image: `https://${process.env.AWS_S3_BUCKET_NAME}.s3.dualstack.${process.env.AWS_REGION}.amazonaws.com/reports/reportType3.png`,
quote: {
title: "호기심 대장 신청자",
description: "호기심이 가득해서, 언제나 새로운 작가를 탐색해요."
},
condition: "서로 다른 작가 5명 이상에게 커미션을 신청"
},
{
image: "https://example.com/character4.png",
image: `https://${process.env.AWS_S3_BUCKET_NAME}.s3.dualstack.${process.env.AWS_REGION}.amazonaws.com/reports/reportType4.png`,
quote: {
title: "숨겨진 보석 발굴가",
description: "\"빛나는 원석을 내가 발견했다!\" 성장하는 작가님들의 첫걸음을 함께한 당신, 멋져요."
},
condition: "팔로워 수가 0명인 작가에게 신청 2회 이상"
},
{
image: "https://example.com/character5.png",
image: `https://${process.env.AWS_S3_BUCKET_NAME}.s3.dualstack.${process.env.AWS_REGION}.amazonaws.com/reports/reportType5.png`,
quote: {
title: "빠른 피드백러",
description: "\"작가님, 이번 커미션 최고였어요!\" 정성 가득한 피드백으로 건강한 커미션 문화를 만들어가요."
Expand Down
6 changes: 3 additions & 3 deletions src/common/swagger/commission.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@
"image": {
"type": "string",
"format": "binary",
"description": "업로드할 이미지 파일 (JPG, PNG, 최대 5MB)"
"description": "업로드할 이미지 파일 (JPG, PNG, 최대 10MB)"
}
},
"required": ["image"]
Expand Down Expand Up @@ -460,8 +460,8 @@
"data": {
"type": "object",
"properties": {
"maxSize": { "type": "string", "example": "5MB" },
"receivedSize": { "type": "string", "example": "7.2MB" }
"maxSize": { "type": "string", "example": "10MB" },
"receivedSize": { "type": "string", "example": "15MB" }
}
}
}
Expand Down