103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
|
|
import { Injectable, Logger } from '@nestjs/common';
|
|
import {
|
|
S3Client,
|
|
DeleteObjectCommand,
|
|
GetObjectCommand,
|
|
ListObjectsCommand,
|
|
PutObjectCommand,
|
|
} from '@aws-sdk/client-s3';
|
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
import { Upload } from '@aws-sdk/lib-storage';
|
|
import { ConfigService } from '@nestjs/config';
|
|
|
|
@Injectable()
|
|
export class S3Service {
|
|
private s3Client: S3Client;
|
|
private readonly logger = new Logger(S3Service.name);
|
|
|
|
constructor(private configService: ConfigService) {
|
|
this.s3Client = new S3Client({
|
|
region: this.configService.get('AWS_REGION'),
|
|
endpoint: this.configService.get('AWS_ENDPOINT_URL'),
|
|
credentials: {
|
|
accessKeyId: this.configService.get('AWS_ACCESS_KEY_ID'),
|
|
secretAccessKey: this.configService.get('AWS_SECRET_ACCESS_KEY'),
|
|
},
|
|
forcePathStyle: true, // Needed for non-AWS S3 compatible services
|
|
});
|
|
}
|
|
|
|
async getObject(key: string) {
|
|
try {
|
|
const command = new GetObjectCommand({
|
|
Bucket: this.configService.get('AWS_S3_BUCKET_NAME'),
|
|
Key: key,
|
|
});
|
|
|
|
const response = await this.s3Client.send(command);
|
|
return response;
|
|
} catch (error) {
|
|
this.logger.error(`Error getting object from S3: ${error.message}`);
|
|
throw error;
|
|
}
|
|
}
|
|
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('AWS_S3_BUCKET_NAME'),
|
|
Key: key,
|
|
Body: file.buffer,
|
|
ContentType: file.mimetype,
|
|
});
|
|
|
|
await this.s3Client.send(command);
|
|
return key;
|
|
} catch (error) {
|
|
this.logger.error(`Error uploading file to S3: ${error.message}`);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async deleteFile(key: string): Promise<void> {
|
|
try {
|
|
const command = new DeleteObjectCommand({
|
|
Bucket: this.configService.get('AWS_S3_BUCKET_NAME'),
|
|
Key: key,
|
|
});
|
|
|
|
await this.s3Client.send(command);
|
|
} catch (error) {
|
|
this.logger.error(`Error deleting file from S3: ${error.message}`);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async getFileUrl(key: string): Promise<string> {
|
|
const command = new GetObjectCommand({
|
|
Bucket: this.configService.get('AWS_S3_BUCKET_NAME'),
|
|
Key: key,
|
|
});
|
|
|
|
const url = await getSignedUrl(this.s3Client, command, { expiresIn: 3600 }); // URL expires in 1 hour
|
|
return url;
|
|
}
|
|
|
|
async testConnection(): Promise<boolean> {
|
|
try {
|
|
await this.getObject('test-connection');
|
|
return true;
|
|
} catch (error) {
|
|
if (error.name === 'NoSuchKey') {
|
|
// This is expected as we're just testing connection
|
|
return true;
|
|
}
|
|
this.logger.error('Failed to connect to S3', error);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|