multer-google-storage
Version:
Streaming multer storage engine for Google Cloud Storage
104 lines (79 loc) • 2.95 kB
text/typescript
import * as multer from 'multer';
import * as Storage from '@google-cloud/storage';
import { Bucket, ConfigurationObject } from '@google-cloud/storage';
import * as uuid from 'uuid/v1';
import { Request } from 'express';
const storage: (options?:ConfigurationObject)=>Storage = require('@google-cloud/storage');
export default class MulterGoogleCloudStorage implements multer.StorageEngine {
private gcobj: Storage;
private gcsBucket: Bucket;
private options: ConfigurationObject & { acl?: string, bucket?: string, contentType?: ContentTypeFunction };
getFilename(req, file, cb) {
cb(null,`${uuid()}_${file.originalname}`);
}
getDestination( req, file, cb ) {
cb( null, '' );
}
public getContentType: ContentTypeFunction = (req, file) => {
return undefined;
}
constructor(opts?: ConfigurationObject & { filename?: any, bucket?:string, contentType?: ContentTypeFunction }) {
opts = opts || {};
this.getFilename = (opts.filename || this.getFilename);
this.getContentType = (opts.contentType || this.getContentType);
opts.bucket = (opts.bucket || process.env.GCS_BUCKET || null);
opts.projectId = opts.projectId || process.env.GCLOUD_PROJECT || null;
opts.keyFilename = opts.keyFilename || process.env.GCS_KEYFILE || null;
if (!opts.bucket) {
throw new Error('You have to specify bucket for Google Cloud Storage to work.');
}
if (!opts.projectId) {
throw new Error('You have to specify project id for Google Cloud Storage to work.');
}
if (!opts.keyFilename) {
throw new Error('You have to specify credentials key file for Google Cloud Storage to work.');
}
this.gcobj = storage({
projectId: opts.projectId,
keyFilename: opts.keyFilename
});
this.gcsBucket = this.gcobj.bucket(opts.bucket);
this.options = opts;
}
_handleFile = (req, file, cb) => {
this.getDestination(req, file, (err, destination) => {
if (err) {
return cb(err);
}
this.getFilename(req, file, (err, filename) => {
if (err) {
return cb(err);
}
var gcFile = this.gcsBucket.file(filename);
const streamOpts: Storage.WriteStreamOptions = {
predefinedAcl: this.options.acl || 'private'
};
const contentType = this.getContentType(req, file);
if (contentType) {
streamOpts.metadata = {contentType};
}
file.stream.pipe(
gcFile.createWriteStream(streamOpts))
.on('error', (err) => cb(err))
.on('finish', (file) => cb(null, {
path: `https://${this.options.bucket}.storage.googleapis.com/${filename}`,
filename: filename
})
);
});
});
}
_removeFile = (req, file, cb) => {
var gcFile = this.gcsBucket.file(file.filename);
gcFile.delete();
};
}
export function storageEngine(opts?: ConfigurationObject & { filename?: any, bucket?:string }){
return new MulterGoogleCloudStorage(opts);
}
export type ContentTypeFunction = (req: Request, file: Express.Multer.File) => string | undefined;