UNPKG

express-storage

Version:

A simple and powerful file upload and storage management package for Express.js applications. Supports multiple storage drivers including S3, GCS, OCI, and local storage with presigned URL support.

135 lines 4.79 kB
import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { BaseStorageDriver } from './base.driver.js'; /** * AWS S3 storage driver */ export class S3StorageDriver extends BaseStorageDriver { constructor(config) { super(config); this.bucketName = config.bucketName; this.region = config.awsRegion; this.s3Client = new S3Client({ region: this.region, credentials: { accessKeyId: config.awsAccessKey, secretAccessKey: config.awsSecretKey, }, }); } /** * Upload file to S3 */ async upload(file) { try { // Validate file const validationErrors = this.validateFile(file); if (validationErrors.length > 0) { return this.createErrorResult(validationErrors.join(', ')); } // Generate unique filename const fileName = this.generateFileName(file.originalname); // Create S3 upload command const uploadCommand = new PutObjectCommand({ Bucket: this.bucketName, Key: fileName, Body: file.buffer, ContentType: file.mimetype, ContentLength: file.size, }); // Upload to S3 await this.s3Client.send(uploadCommand); // Generate file URL const fileUrl = `https://${this.bucketName}.s3.${this.region}.amazonaws.com/${fileName}`; return this.createSuccessResult(fileName, fileUrl); } catch (error) { return this.createErrorResult(error instanceof Error ? error.message : 'Failed to upload file to S3'); } } /** * Generate presigned upload URL */ async generateUploadUrl(fileName) { try { const uploadCommand = new PutObjectCommand({ Bucket: this.bucketName, Key: fileName, ContentType: 'application/octet-stream', }); const uploadUrl = await getSignedUrl(this.s3Client, uploadCommand, { expiresIn: this.getPresignedUrlExpiry(), }); return this.createPresignedSuccessResult(uploadUrl); } catch (error) { return this.createPresignedErrorResult(error instanceof Error ? error.message : 'Failed to generate upload URL'); } } /** * Generate presigned view URL */ async generateViewUrl(fileName) { try { const getCommand = new GetObjectCommand({ Bucket: this.bucketName, Key: fileName, }); const viewUrl = await getSignedUrl(this.s3Client, getCommand, { expiresIn: this.getPresignedUrlExpiry(), }); return this.createPresignedSuccessResult(undefined, viewUrl); } catch (error) { return this.createPresignedErrorResult(error instanceof Error ? error.message : 'Failed to generate view URL'); } } /** * Delete file from S3 */ async delete(fileName) { try { const deleteCommand = new DeleteObjectCommand({ Bucket: this.bucketName, Key: fileName, }); await this.s3Client.send(deleteCommand); return true; } catch (error) { return false; } } } /** * AWS S3 presigned storage driver */ export class S3PresignedStorageDriver extends S3StorageDriver { constructor(config) { super(config); } /** * Override upload to return presigned URL instead of direct upload */ async upload(file) { try { // Validate file const validationErrors = this.validateFile(file); if (validationErrors.length > 0) { return this.createErrorResult(validationErrors.join(', ')); } // Generate unique filename const fileName = this.generateFileName(file.originalname); // Generate presigned upload URL const presignedResult = await this.generateUploadUrl(fileName); if (!presignedResult.success) { return this.createErrorResult(presignedResult.error || 'Failed to generate presigned URL'); } return this.createSuccessResult(fileName, presignedResult.uploadUrl); } catch (error) { return this.createErrorResult(error instanceof Error ? error.message : 'Failed to generate presigned URL'); } } } //# sourceMappingURL=s3.driver.js.map