Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | import {
S3Client,
PutObjectCommand,
DeleteObjectCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { config } from '../config/env';
import { InternalError } from '../common/errors';
import { IImageStorageService } from './imageStorageService.interface';
import { getLogger } from '../common/logger';
const logger = getLogger('ImageStorageService');
export class ImageStorageService implements IImageStorageService {
private s3Client: S3Client;
private bucketName: string;
constructor() {
this.s3Client = new S3Client({ region: config.awsRegion });
this.bucketName = config.s3BucketName;
}
async getPresignedUploadUrl(
imageId: string,
contentType: string,
expiresIn = 300
): Promise<string> {
logger.info('getPresignedUploadUrl called', {
imageId,
contentType,
expiresIn,
});
try {
const command = new PutObjectCommand({
Bucket: this.bucketName,
Key: imageId,
// Don't include ContentType here - let client set it during upload
// This avoids signature mismatch if client doesn't send exact header
});
const signedUrl = await getSignedUrl(this.s3Client, command, {
expiresIn,
});
logger.info(`Presigned URL generated for: ${imageId}`);
return signedUrl;
} catch (error) {
logger.error(
`S3 presigned URL generation error: ${(error as Error).message}`
);
throw new InternalError('Failed to generate presigned upload URL');
}
}
async deleteImage(imageId: string): Promise<void> {
logger.info('deleteImage called', { imageId });
try {
const command = new DeleteObjectCommand({
Bucket: this.bucketName,
Key: imageId,
});
await this.s3Client.send(command);
logger.info(`Image deleted from S3: ${imageId}`);
} catch (error) {
logger.error(`S3 delete error: ${(error as Error).message}`);
throw new InternalError('Failed to delete image from storage');
}
}
}
|