b68/packages/api/helpers/upload.factory.ts

83 lines
2.6 KiB
TypeScript

import { S3Client } from '@aws-sdk/client-s3'
import multer from 'multer'
import multerS3 from 'multer-s3'
import path from 'path'
import napiNanoId from 'napi-nanoid'
import { configKeys } from '..'
interface UploadFactoryOptions {
region: string
bucket: string
accessKey: string
secretKey: string
}
interface UploaderConfig {
folder: string
mimeFilters: string[]
}
export class UploadFactory {
private options: UploadFactoryOptions & Partial<UploaderConfig>
private s3Client: S3Client
constructor(options?: Partial<UploadFactoryOptions>) {
this.options = {
bucket: options?.bucket || configKeys.S3_BUCKET_NAME || '',
region: options?.region || configKeys.S3_BUCKET_REGION || '',
accessKey: options?.accessKey || configKeys.S3_CLIENT_ID || '',
secretKey: options?.secretKey || configKeys.S3_CLIENT_SECRET || '',
}
this.s3Client = new S3Client({
region: this.options.region,
credentials: {
accessKeyId: this.options.accessKey,
secretAccessKey: this.options.secretKey,
},
})
}
public get serviceName(): string {
return 'aws:' + this.options.bucket
}
public getUploader(
config?: Partial<UploadFactoryOptions & UploaderConfig>
) {
const finalOptions = {
...this.options,
...(config || {}),
}
return multer({
fileFilter(_req, file, cb) {
const res = finalOptions.mimeFilters
? finalOptions.mimeFilters.includes(file.mimetype)
: true
cb(null, res)
},
storage: multerS3({
s3: this.s3Client,
bucket: this.options.bucket,
acl: 'public-read',
contentType: multerS3.AUTO_CONTENT_TYPE,
metadata: function (_req, file, cb) {
const meta = {
fieldName: file.fieldname,
fileName: file.originalname,
uploadOn: new Date().toISOString(),
}
cb(null, meta)
},
key: function (_req, file, cb) {
const key: string[] = []
if (finalOptions.folder) key.push(finalOptions.folder)
const value = napiNanoId.nanoid()
const ext = path.extname(file.originalname)
key.push(value + ext)
cb(null, key.join('/'))
},
}),
})
}
}