72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
import { Injectable, Logger, InternalServerErrorException } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
|
|
import { S3File } from '../interfaces/s3-file.interface';
|
|
|
|
@Injectable()
|
|
export class S3Service {
|
|
private readonly s3Client: S3Client;
|
|
private readonly logger = new Logger(S3Service.name);
|
|
|
|
constructor(private readonly configService: ConfigService) {
|
|
this.s3Client = new S3Client({
|
|
region: this.configService.get<string>('AWS_REGION'),
|
|
credentials: {
|
|
accessKeyId: this.configService.get<string>('AWS_ACCESS_KEY_ID'),
|
|
secretAccessKey: this.configService.get<string>('AWS_SECRET_ACCESS_KEY'),
|
|
},
|
|
endpoint: this.configService.get<string>('AWS_ENDPOINT_URL'),
|
|
forcePathStyle: true, // Required for Contabo Object Storage
|
|
});
|
|
}
|
|
|
|
async uploadFile(file: Express.Multer.File, folder: string): Promise<string> {
|
|
try {
|
|
const key = `${folder}/${Date.now()}-${file.originalname}`;
|
|
|
|
const command = new PutObjectCommand({
|
|
Bucket: this.configService.get<string>('AWS_S3_BUCKET_NAME'),
|
|
Key: key,
|
|
Body: file.buffer,
|
|
ContentType: file.mimetype,
|
|
});
|
|
|
|
await this.s3Client.send(command);
|
|
this.logger.debug(`File uploaded successfully: ${key}`);
|
|
|
|
return key;
|
|
} catch (error) {
|
|
this.logger.error(`Error uploading file to S3: ${error.message}`);
|
|
throw new InternalServerErrorException('Failed to upload file to storage');
|
|
}
|
|
}
|
|
|
|
async getFile(key: string): Promise<S3File> {
|
|
try {
|
|
const command = new GetObjectCommand({
|
|
Bucket: this.configService.get<string>('AWS_S3_BUCKET_NAME'),
|
|
Key: key,
|
|
});
|
|
|
|
const response = await this.s3Client.send(command);
|
|
|
|
const chunks = [];
|
|
for await (const chunk of response.Body as any) {
|
|
chunks.push(chunk);
|
|
}
|
|
const buffer = Buffer.concat(chunks);
|
|
|
|
return {
|
|
buffer,
|
|
contentType: response.ContentType || 'application/octet-stream',
|
|
contentLength: response.ContentLength || buffer.length,
|
|
fileName: key.split('/').pop() || 'download',
|
|
};
|
|
} catch (error) {
|
|
this.logger.error(`Error getting file from S3: ${error.message}`);
|
|
throw new InternalServerErrorException('Failed to retrieve file from storage');
|
|
}
|
|
}
|
|
}
|
|
|
|
|