기존의 file.service.ts관련 구조(dynamic module)를 유지하면서 aws s3를 파일 서버로 사용하고자 함.
// /src/config/file/s3/client.module.ts 일부
case FileClientType.S3:
return {
module: FileConfigModule,
providers: [
{
provide: FILE_CLIENT_SERVICE,
useClass: S3ClientService,
},
],
exports: [FILE_CLIENT_SERVICE],
};
// /src/config/file/s3/client.service.ts
import { BadRequestException, Injectable } from "@nestjs/common";
import { FileClientService } from "../client.service";
import { ConfigService } from "@nestjs/config";
import * as AWS from "aws-sdk";
@Injectable()
export class S3ClientService implements FileClientService {
private readonly S3: AWS.S3;
private readonly bucket: string;
constructor(private readonly configService: ConfigService) {
AWS.config.update({
credentials: {
accessKeyId: configService.get("S3_ACCESS_KEY"),
secretAccessKey: configService.get("S3_SECRET_KEY"),
},
region: configService.get("S3_BUCKET_REGION"),
});
this.S3 = new AWS.S3();
this.bucket = this.configService.get("S3_BUCKET_NAME");
}
async uploadFile(
key: string,
file: Buffer,
size: number,
createdAt: Date,
originalName: string,
mimeType: string
) {
const metaData = {
"Content-Type": mimeType,
createdAt: createdAt.toUTCString(),
originalName: encodeURI(originalName),
};
try {
await this.S3.putObject({
Bucket: `${this.bucket}/files`,
Key: key,
Body: file,
ContentType: mimeType,
Metadata: metaData,
}).promise();
} catch (err) {
throw new BadRequestException(err.message);
}
}
async getFile(key: string) {
try {
return await this.S3.getObject({
Bucket: `${this.bucket}/files`,
Key: key,
}).createReadStream();
} catch (err) {
throw new BadRequestException(err.message);
}
}
async removeFile(key: string) {
try {
return await this.S3.deleteObject({
Bucket: `${this.bucket}/files`,
Key: key,
}).createReadStream();
} catch (err) {
throw new BadRequestException(err.message);
}
}
}
파일이 위치할 디렉토리(?)
까지를 의미하는데 모두 /files
를 빼먹어서 버킷이 존재하지 않는다는 오류를 뱉어냄.aws-sdk v3이 있지만 현재 구조에 어떻게 적용시켜야 할 지 잘 이해가 되지 않아서(...)일단 v2를 사용했는데, v3로 마이그레이션이 가능하면 시도해보는 것도 좋을 듯.