Skip to content

Commit

Permalink
feat(contentType): Add custom opts to set uploaded content type
Browse files Browse the repository at this point in the history
fix #3
  • Loading branch information
Rémi Parpaillon authored and arozar committed Jan 28, 2019
1 parent fe4bc5e commit 43bfa22
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ The constructor of the MulterGoogleCloudStorage class can be passed an optional
|`projectId`|`string`|`"test-prj-1234"`|
|`filename`| `function`|`(request, file, callback): void`|
|`bucket`|`string`|`"mybucketname"`|
|`contentType`|`function`|`(request, file): string`|

#### Custom file naming
If you need to customize the naming of files then you are able to provide a function that will be called before uploading the file. The third argument of the function must be a standard node callback so pass any error in the first argument (or null on sucess) and the string name of the file on success.

getFilename(req, file, cb) {
cb(null,`${uuid()}_${file.originalname}`);
}

5 changes: 5 additions & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
/// <reference types="google-cloud__storage" />
import * as multer from 'multer';
import { ConfigurationObject } from '@google-cloud/storage';
import { Request } from 'express';
export default class MulterGoogleCloudStorage implements multer.StorageEngine {
private gcobj;
private gcsBucket;
private options;
getFilename(req: any, file: any, cb: any): void;
getDestination(req: any, file: any, cb: any): void;
getContentType: ContentTypeFunction;
constructor(opts?: ConfigurationObject & {
filename?: any;
bucket?: string;
contentType?: ContentTypeFunction;
});
_handleFile: (req: any, file: any, cb: any) => void;
_removeFile: (req: any, file: any, cb: any) => void;
Expand All @@ -17,3 +21,4 @@ export declare function storageEngine(opts?: ConfigurationObject & {
filename?: any;
bucket?: string;
}): MulterGoogleCloudStorage;
export declare type ContentTypeFunction = (req: Request, file: Express.Multer.File) => string | undefined;
15 changes: 13 additions & 2 deletions lib/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/index.test.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
2 changes: 1 addition & 1 deletion lib/index.test.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"license": "MIT",
"dependencies": {
"@google-cloud/storage": "^1.1.1",
"@types/express": "^4.16.1",
"@types/google-cloud__storage": "^1.1.1",
"multer": "^1.3.0",
"uuid": "^3.1.0"
Expand Down
38 changes: 29 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as multer from 'multer';
import { Storage, Bucket, ConfigurationObject } from '@google-cloud/storage';
import * as Storage from '@google-cloud/storage';
import { Bucket, ConfigurationObject } from '@google-cloud/storage';
import * as uuid from 'uuid/v1';
const storage: (options?:ConfigurationObject)=>Storage = require('@google-cloud/storage');
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 };
private options: ConfigurationObject & { acl?: string, bucket?: string, contentType?: ContentTypeFunction };

getFilename(req, file, cb) {
cb(null,`${uuid()}_${file.originalname}`);
Expand All @@ -16,10 +18,15 @@ export default class MulterGoogleCloudStorage implements multer.StorageEngine {
cb( null, '' );
}

constructor(opts?: ConfigurationObject & { filename?: any, bucket?:string }) {
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;
Expand Down Expand Up @@ -59,14 +66,25 @@ export default class MulterGoogleCloudStorage implements multer.StorageEngine {
return cb(err);
}
var gcFile = this.gcsBucket.file(filename);
file.stream.pipe(gcFile.createWriteStream({ predefinedAcl: this.options.acl || 'private' }))

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
})
);

});

});
Expand All @@ -78,6 +96,8 @@ export default class MulterGoogleCloudStorage implements multer.StorageEngine {
}

export function storageEngine(opts?: ConfigurationObject & { filename?: any, bucket?:string }){

return new MulterGoogleCloudStorage(opts);
}
}

export type ContentTypeFunction = (req: Request, file: Express.Multer.File) => string | undefined;

0 comments on commit 43bfa22

Please sign in to comment.