Skip to content

Instantly share code, notes, and snippets.

@maneetgoyal
Last active February 8, 2024 17:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maneetgoyal/c724e8e44ad3c04a6609eba740802e5a to your computer and use it in GitHub Desktop.
Save maneetgoyal/c724e8e44ad3c04a6609eba740802e5a to your computer and use it in GitHub Desktop.
Multer Storage Engine in TypeScript
import { createWriteStream, unlink } from "fs";
import type { PathLike } from "fs";
import type { Request } from "express";
type Maybe<T> = T | null | undefined;
type ResponseCallback<T> = (err: Error | null, payload?: Maybe<T>) => void;
type RequestHandler<T> = (req: Request, file: Express.Multer.File, responseCb: ResponseCallback<T>) => void;
/**
* Custom Multer Storage Engine for uploading file to AWS S3
* Ref: https://github.com/expressjs/multer/blob/master/StorageEngine.md
* Example Usage:
* ```ts
* const storageEngine = new MulterS3StorageEngine((_req, file, responseCb) => {
* responseCb(null, `/var/www/uploads/${file.originalname}`);
* });
* ```
*/
export class MulterS3StorageEngine {
/**
* Tells the engine where to save the file.
* @param _req
* @param _file
* @param responseCb
*/
getDestination: RequestHandler<PathLike> = (_req, _file, responseCb) => {
responseCb(null, "/dev/null");
};
/**
* Stores the file and returns information on how to access the file in the future.
* The information you provide in the callback will be merged with multer's file object, and then presented to the user via `req.files`.
* @param req
* @param file
* @param responseCb
*/
_handleFile: RequestHandler<unknown> = (
req: Request,
file: Express.Multer.File,
responseCb: ResponseCallback<unknown>
) => {
this.getDestination(req, file, (err, path) => {
if (err !== null) {
responseCb(err);
}
if (path !== null && path !== undefined) {
const outStream = createWriteStream(path);
file.stream.pipe(outStream);
outStream.on("error", responseCb);
outStream.on("finish", () => {
responseCb(null, { path, size: outStream.bytesWritten });
});
}
});
};
/**
* Removes the file if an error is encounter during file stream handling.
* Multer will decide which files to delete and when.
* @param _req
* @param file
* @param responseCb
*/
_removeFile: RequestHandler<unknown> = (
_req: Request,
file: Express.Multer.File,
responseCb: ResponseCallback<unknown>
) => {
unlink(file.path, responseCb);
};
constructor(destination?: RequestHandler<string>) {
this.getDestination = destination ?? this.getDestination;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment