Skip to content

Commit f26fafd

Browse files
committed
πŸ› fix: 파일 μ—…λ‘œλ“œ λ‚œμˆ˜κ°’ 이름 μƒμ„±ν•˜λ„λ‘ λ³€κ²½
1 parent f6c2235 commit f26fafd

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

β€Žserver/src/file/controller/file.controller.tsβ€Ž

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class FileController {
4444
message: 'file size limit',
4545
}),
4646
new FileTypeValidator({
47-
fileType: /image\/(png|jpg|jpeg|webp)/,
47+
fileType: /image\/(png|jpg|jpeg|webp|gif)/,
4848
skipMagicNumbersValidation: true,
4949
}),
5050
],
@@ -54,9 +54,7 @@ export class FileController {
5454
@Query() query: UploadFileQueryRequestDto,
5555
@CurrentUser() user: Payload,
5656
) {
57-
file.path = (
58-
await this.fileService.handleUpload(file, query.uploadType)
59-
).savedPath;
57+
file.path = await this.fileService.handleUpload(file, query.uploadType);
6058

6159
return ApiResponse.responseWithData(
6260
'파일 μ—…λ‘œλ“œμ— μ„±κ³΅ν–ˆμŠ΅λ‹ˆλ‹€.',

β€Žserver/src/file/service/file.service.tsβ€Ž

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { WinstonLoggerService } from '../../common/logger/logger.service';
77
import * as fs from 'fs/promises';
88
import * as path from 'path';
99
import { FileUploadType } from '../../common/disk/file-type';
10+
import * as uuid from 'uuid';
1011

1112
@Injectable()
1213
export class FileService {
@@ -23,14 +24,13 @@ export class FileService {
2324

2425
await this.ensureDirectory(targetDir);
2526

26-
const filePath = path.join(targetDir, file.originalname);
27+
const ext = path.extname(file.originalname);
28+
const fileName = `${uuid.v4()}${ext}`;
29+
const filePath = path.join(targetDir, fileName);
30+
2731
await fs.writeFile(filePath, file.buffer);
2832

29-
return {
30-
success: true,
31-
uploadType,
32-
savedPath: filePath,
33-
};
33+
return filePath;
3434
}
3535

3636
private async ensureDirectory(dir: string) {

β€Žserver/test/file/e2e/upload.e2e-spec.tsβ€Ž

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import {
88
import { User } from '../../../src/user/entity/user.entity';
99
import { UserRepository } from '../../../src/user/repository/user.repository';
1010
import { UserFixture } from '../../fixture/user.fixture';
11-
import * as path from 'path';
1211
import TestAgent from 'supertest/lib/agent';
1312
import { FileRepository } from '../../../src/file/repository/file.repository';
1413
import { createAccessToken } from '../../jest.setup';
1514
import * as fs from 'fs/promises';
15+
import * as uuid from 'uuid';
1616

1717
const URL = '/api/file';
1818

@@ -21,6 +21,7 @@ describe(`POST ${URL} E2E Test`, () => {
2121
let agent: TestAgent;
2222
let user: User;
2323
let fileRepository: FileRepository;
24+
const fileRandomName = 'test-random-uuid-file-name';
2425

2526
beforeAll(async () => {
2627
app = global.testApp;
@@ -35,6 +36,7 @@ describe(`POST ${URL} E2E Test`, () => {
3536
beforeEach(() => {
3637
jest.spyOn(fs, 'writeFile').mockResolvedValue(undefined);
3738
jest.spyOn(fs, 'mkdir').mockResolvedValue(undefined);
39+
jest.spyOn(uuid, 'v4').mockReturnValue(fileRandomName as any);
3840
});
3941

4042
it('[401] μΈμ¦λ˜μ§€ μ•Šμ€ μ‚¬μš©μžκ°€ μš”μ²­ν•  경우 파일 μ—…λ‘œλ“œλ₯Ό μ‹€νŒ¨ν•œλ‹€.', async () => {
@@ -69,6 +71,15 @@ describe(`POST ${URL} E2E Test`, () => {
6971
const { data } = response.body;
7072
expect(response.status).toBe(HttpStatus.BAD_REQUEST);
7173
expect(data).toBeUndefined();
74+
75+
// DB, Redis when
76+
const savedFile = await fileRepository.findOneBy({
77+
originalName: 'test.png',
78+
mimetype: 'image/png',
79+
});
80+
81+
// DB, Redis then
82+
expect(savedFile).toBeNull();
7283
});
7384

7485
it('[400] 파일 νƒ€μž…μ΄ μΌμΉ˜ν•˜μ§€ μ•Šμ„ 경우 파일 μ—…λ‘œλ“œλ₯Ό μ‹€νŒ¨ν•œλ‹€. ', async () => {
@@ -90,6 +101,15 @@ describe(`POST ${URL} E2E Test`, () => {
90101
const { data } = response.body;
91102
expect(response.status).toBe(HttpStatus.BAD_REQUEST);
92103
expect(data).toBeUndefined();
104+
105+
// DB, Redis when
106+
const savedFile = await fileRepository.findOneBy({
107+
originalName: 'test.png',
108+
mimetype: 'image/png',
109+
});
110+
111+
// DB, Redis then
112+
expect(savedFile).toBeNull();
93113
});
94114

95115
it('[400] 파일 크기가 μΌμΉ˜ν•˜μ§€ μ•Šμ„ 경우 파일 μ—…λ‘œλ“œλ₯Ό μ‹€νŒ¨ν•œλ‹€. ', async () => {
@@ -111,6 +131,15 @@ describe(`POST ${URL} E2E Test`, () => {
111131
const { data } = response.body;
112132
expect(response.status).toBe(HttpStatus.BAD_REQUEST);
113133
expect(data).toBeUndefined();
134+
135+
// DB, Redis when
136+
const savedFile = await fileRepository.findOneBy({
137+
originalName: 'test.png',
138+
mimetype: 'image/png',
139+
});
140+
141+
// DB, Redis then
142+
expect(savedFile).toBeNull();
114143
});
115144

116145
it('[201] νŒŒμΌμ„ 포함할 경우 파일 μ—…λ‘œλ“œλ₯Ό μ„±κ³΅ν•œλ‹€.', async () => {
@@ -135,8 +164,8 @@ describe(`POST ${URL} E2E Test`, () => {
135164
id: expect.any(Number),
136165
originalName: 'test.png',
137166
mimetype: 'image/png',
138-
size: expect.any(Number),
139-
url: expect.any(String),
167+
size: 1024,
168+
url: expect.stringContaining(fileRandomName),
140169
userId: user.id,
141170
createdAt: expect.any(String),
142171
});

0 commit comments

Comments
Β (0)