👉 postman 에서 실행해본 결과
위 사진과 같이 form-data 로 여러 파일을 첨부하고 AWS s3 bucket 에 업로드 한 후 값들을 db 에 저장하고 저장된 데이터들을 response 로 리턴해주는 기능을 만들어볼 것입니다 🏄♀️
🐱 현재 이 프로젝트는 nestjs 프레임워크를 사용하고 있습니다.
1. 패키지 설치 (aws-sdk, multer, multer-s3)
npm install aws-sdk multer multer-s3 --save
https://www.npmjs.com/package/multer-s3
이 포스트에서는 s3 bucket 업로드를 하고 있으므로 multer-s3 패키지 까지 같이 설치해 줍니다.
네스트 공식문서에도 파일업로드 하는 예제가 있지만 그 예제에는 s3 업로드 까지는 다루고 있지 않으므로 따로 설치해주셔야 합니다.
2. upload-file 서비스, 컨트롤러 생성 cli
이미 몇번 리소스를 생성해본 분들은 아시겠지만 nestjs 에서는 cli 로 리소스 파일을 자동 생성할 수 있습니다.
https://docs.nestjs.com/cli/usages#cli-command-reference
위 문서에서 보면 다양한 schematics 들을 cli 로 생성 할 수 있습니다.
현재 포스트에서는 service, controlle, module 을 따로 생성하겠습니다.
(1) module 생성
nest g mo upload-file
(2) constroller 생성
nest g co upload-file
(3) service 생성
nest g s upload-file
생성후 기본적인 구조는 공식문서를 참고해 주세요
저는 상기 사진과 같이 파일 구조를 짰습니다.
(dto, exception 은 추가하지 않아도 됩니다.)
3. upload-file 엔티티 생성하기
- upload-file/entity/upload-file.entity.ts
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
@Entity("upload_file")
export class UploadFile {
@PrimaryGeneratedColumn("uuid")
id:string;
@Column()
originalName: string;
@Column()
encoding: string;
@Column()
mimeType: string;
@Column("decimal", { precision: 10, scale: 2 })
size: number;
@Column({ comment: "s3 업로드된 localtion url" })
url: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
s3에 값을 업로드 할 때 받을 수 있는 meta data 들을 upload-file 테이블 필드에도 추가해주었습니다.
4. upload-file 리포지토리 생성하기
typeorm 은 사용자 지정 저장소 라는 기능을 제공합니다. 커스텀 리포지토리를 사용하면 기본 리포지토리 클래스를 확장하고 몇 가지 특수 메서드를 사용하여 강화할 수 있습니다.
추가적인 내용은 typeorm 공식 홈페이지에 있습니다.
https://typeorm.io/#/custom-repository
- upload-file/upload-file.repository.ts
import { EntityRepository, Repository } from "typeorm";
import { UploadFile } from "./entity/upload-file.entity";
@EntityRepository(UploadFile)
export class UploadFileRepository extends Repository<UploadFile> {}
5. aws-sdk, multer, multer-s3 설치하기
업로드에 필요한 패키지를 설치해줍니다.
- npm
npm install aws-sdk multer multer-s3 --save
공식문서에서는 multer 만을 다루고 있으나
본 포스팅에서는 aws 의 s3 bucket 으로 파일을 업로드 할 것이기 때문에 위의 3 패키지 모두 설치해줍니다!
(s3 bucket 이 이미 생성되어있고 aws accesskey, secretkey, s3 bucket name 을 모두 안다는 가정하에 진행합니다.)
6. upload-file 컨트롤러 로직
- upload-file.controller.ts
import {
Controller,
Post,
UploadedFiles,
UseInterceptors,
} from '@nestjs/common';
import * as AWS from 'aws-sdk';
import * as multerS3 from 'multer-s3';
import { FilesInterceptor } from '@nestjs/platform-express/multer/interceptors/files.interceptor';
import { UploadFileService } from './upload-file.service';
// AWS S3
const s3 = new AWS.S3();
AWS.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: 'ap-northeast-2'
});
@Controller('/file')
export class UploadFileController {
constructor(private readonly UploadFileService: UploadFileService) { }
@Post()
@UseInterceptors(FilesInterceptor('file', 10, {
storage: multerS3({
s3: s3,
bucket: process.env.AWS_S3_BUCKET_NAME,
acl: 'public-read',
key: function (request, file, cb) {
cb(null, `${Date.now().toString()}-${file.originalname}`);
},
}),
limits: {}
}),
)
async uploadFile(
@UploadedFiles() files: Express.MulterS3.File[],
) {
return this.UploadFileService.uploadFile(files);
}
}
1) aws s3 config 설정
아래와 코드와 같이 aws access key, secret key 가 필요합니다.
저는 .env 파일의 환경변수로 설정했습니다.
import * as AWS from 'aws-sdk';
import * as multerS3 from 'multer-s3';
// AWS S3
const s3 = new AWS.S3();
AWS.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: 'ap-northeast-2'
});
2) @UseInterceptors 설정
https://docs.nestjs.com/techniques/file-upload#array-of-files
FileInterceptor 에 최대 10장으로 limit 을 줬으므로 10장 까지만 업로드 하능합니다.
파일 사이즈도 limit 을 주고 싶다면 아래 캡처 처럼 limit 에서 여러 파라미터로 옵션을 줄 수 있습니다.
7. upload-file 서비스 로직
- upload-file.service.ts
import { BadRequestException, Injectable } from '@nestjs/common';
import { UploadFileRepository } from './upload-file.repository';
import { UploadFile } from './entity/upload-file.entity';
@Injectable()
export class UploadFileService {
constructor(
private readonly UploadFileRepository: UploadFileRepository
) { }
async uploadFile(
files: Express.MulterS3.File[],
) {
const uploadfiles = [];
for (const element of files) {
const file = new UploadFile();
file.originalName = element.originalname
file.encoding = element.encoding
file.mimeType = element.mimetype
file.size = element.size
file.url = element.location
uploadfiles.push(file)
}
try {
return { "data": await this.UploadFileRepository.save(uploadfiles) };
} catch (error) {
throw new BadRequestException(error.message)
}
}
}
8. 완성!
postman 을 사용하여 api 테스트를 해보았습니다.
nestjs 에서의 POST 는 기본으로 201 코드를 줍니다.
📝 Ref
https://docs.nestjs.com/techniques/file-upload#file-upload
'JavaScript & Node js' 카테고리의 다른 글
[nodejs/strapi] 🚀 강력한 headless 프레임워크 strapi 사용해보기 [2/3] (0) | 2021.10.29 |
---|---|
[nodejs/strapi] 🚀 강력한 headless 프레임워크 strapi 사용해보기 [1/3] (0) | 2021.10.28 |
npm ERR! must provide string spec (0) | 2021.07.13 |
[JavaScript] 정규표현식 (Regular Expression) (0) | 2020.07.07 |
[Redux] 노드 리액트 Redux 기본 구조 만들기! (0) | 2020.07.01 |