Implementing multer diskStorage with Typescript

I'm currently in the process of converting a node.js server to TypeScript.

Here is what my function looks like in Node:

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        const dir = './uploads/';
        mkdirp(dir, err => cb(err, dir));
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname)
    }
});

const upload = multer({
    storage: storage
});

router.post('/test', upload.fields({name: 'image'}), async function (req, res, next) {
...
});

However, I have encountered several errors during this conversion. For instance, I am unable to declare the file argument as type Express.File, 'memoryStorage' does not accept arguments, and mkdirp gives me an error stating that it cannot be called.

Answer №1

Here is my solution that utilizes the type definitions provided by @types/multer.

If you have not done so already, start by installing the type definitions for the multer package:

npm i --save-dev @types/multer

Imports and type aliases

import { Request } from 'express'
import multer, { FileFilterCallback } from 'multer'

type DestinationCallback = (error: Error | null, destination: string) => void
type FileNameCallback = (error: Error | null, filename: string) => void

Setting up storage

export const fileStorage = multer.diskStorage({
    destination: (
        request: Request,
        file: Express.Multer.File,
        callback: DestinationCallback
    ): void => {
        // ...Implementation goes here.
    },

    filename: (
        req: Request, 
        file: Express.Multer.File, 
        callback: FileNameCallback
    ): void => {
        // ...Implementation goes here.
    }
})

Implementing fileFilter

export const fileFilter = (
    request: Request,
    file: Express.Multer.File,
    callback: FileFilterCallback
): void => {
    if (
        file.mimetype === 'image/png' ||
        file.mimetype === 'image/jpg' ||
        file.mimetype === 'image/jpeg'
    ) {
        callback(null, true)
    } else {
        callback(null, false)
    }
}

For better code organization and separation of concerns, consider placing the above two constants in a separate file like config/multer.ts or util/multer.ts

Application

Import and utilize the above constants in your app.ts or server.ts:

app.use(multer({ storage: fileStorage, fileFilter: fileFilter })

Answer №2

The code snippet below successfully generated a unique identifier for my files:

   const uniqueIdGenerator = require('uuid/v1');

   // Setup storage configuration
   const storage = multer.diskStorage({
       destination: function (req: Express.Request, file: Express.Multer.File, callback: (error: Error | null, destination: string) => void) {
        callback(null, './upload/');
    },
    filename: function (req: Request, file: Express.Multer.File, callback: (error: Error | null, filename: string) => void) {
        const uniqueId = uniqueIdGenerator();
        callback(null, uniqueId + '_' + file.originalname);
    }
});

Answer №3

This is how I implemented it in my specific situation.

const uniqueIDGenerator = require('uuid/v1');

const fileSystem = multer.diskStorage({
  destination: (request, file, callBack) => {
    callBack(null, path.resolve('./upload/'))
  },
  filename: (req, file, callback) => {
    const uniqueID = uniqueIDGenerator();
    callback(null, `${uniqueID}-${file.originalname}`);
  }
});

Answer №4

Success! I was able to make it work with some adjustments :)

const fileStorage = multer.diskStorage({
    destination: function (req: Request, _file: any, cb: Function) {
        const path = './uploads/';
        mkdirp(path, (error: NodeJS.ErrnoException) => {
            cb(error, path)
        });
    },
    filename: function (_request: Request, file: any, cb: Function) {
        cb(null, file.originalname)
    }
});

const fileUpload = multer({
    storage: fileStorage
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Build a KeystoneJS website without using the generator-keystone tool

I have the complete collection of sources from a website built on KeystoneJS. I attempted to deploy it on my laptop (without using generator-keystone since all necessary files are already generated), but even after running npm install I encountered error ...

Issue: Debug Failure. Invalid expression: import= for internal module references should have been addressed in a previous transformer

While working on my Nest build script, I encountered the following error message: Error Debug Failure. False expression: import= for internal module references should be handled in an earlier transformer. I am having trouble comprehending what this erro ...

Using Node.js and Express to create a MySQL API that outputs a JSON array as a string

Currently working on setting up an Express API server to fetch data for a portfolio website. I've configured the MySQL table with a JSON data type for the 'images' column, which is supposed to contain multiple image links for a gallery. Howe ...

The connected module appears as an unresolved requirement

In my development environment, I have two local node packages that we'll refer to as pack1 and pack2. The situation is such that pack2 relies on pack1, but pack1 has not been published to npm; instead, it's linked locally using the npm link comma ...

search for a specific value within a nested subfield of an asterisk star field in Firestore

Here is the data I have: { root: { _rEG: { fen: 'value' }, _AS: { fen: 'value' }, _BSSA: { fen: 'value' } } } I would like to query using where('root.*.fen', '==', 'value'). ...

Typescript - optional type when a generic is not given

I am hoping for optionalFields to be of type OptionalFieldsByTopic<Topic> if a generic is not provided, or else OptionalFieldsByTopic<T>. Thank you in advance for the assistance. export interface ICreateItem<T extends Topic = never> { // ...

Error: Expected an Image or Canvas as input

The code snippet below shows the function I was using in Express with request params text to load an image, but unfortunately it's not working as expected. const { Canvas } = require('canvas-constructor') const canvas = require('canvas& ...

Getting the Hostname in a NestJS Controller Function

I am currently utilizing a NestJS application to serve a REST-API. Is there a way for me to obtain the current Hostname within a controller? This is my controller function: async find(@Param('uuid') uuid: string, @Req() req: Request): Promise&l ...

Having trouble with res.redirect not working after the page has been rendered with data?

I have a basic forget password feature set up, where users can request a password change and receive an email with a token. Clicking the link in the email will redirect them to a page where they can input their new password. When I click on the email link ...

Node script causing occasional corruption in JSON file

I am currently developing a Discord bot that pairs up two individuals for a game. This process involves storing their Discord ID, queue status, and opponent in a JSON file. Here is an example of how the data is structured for each user: { "discordId": ...

What are the steps to developing a chat application with MERN stack or another straightforward method?

What is the best way to develop a chat application for direct communication between two individuals? For instance, imagine a website with numerous producers where a consumer wishes to engage in a live chat with a specific producer. Any ideas on how to ach ...

Obtaining the node-webkit GUI object from an HTML file that has been generated by Express

I have developed a node web application using Express and other Node modules. I am interested in turning this web app into a desktop application, and a friend recommended using Node Webkit. Node Webkit allows me to customize the appearance of the app to m ...

Tips for confirming a date format within an Angular application

Recently, I've been diving into the world of Angular Validations to ensure pattern matching and field requirements are met in my projects. Despite finding numerous resources online on how to implement this feature, I've encountered some challenge ...

Encountered an error while attempting to load resource in Node.js

I'm currently working on a project utilizing Node js (Express...). Let me do my best to explain the issue I am encountering. My work is being done on localhost, and the main page of my index.html has buttons that lead to other pages when clicked. I c ...

What steps are involved in constructing Jodit from scratch?

Seeking a non-minified, readable version of Jodit, I attempted to build it myself. However, my lack of experience with composer, node, npm, webpack, TypeScript, and other tools has left me struggling. Is there anyone who can guide me through the process s ...

What could be the cause of this situation?

Recently, I started working on a MERN app using Express. While creating the server with Express, I encountered an error. const express = require("express"); const app = express(); const PATH = require("path"); const LAYOUT = require(&qu ...

What could be causing Heroku to encounter issues while compiling the build of the project?

I'm experiencing a challenge in deploying my react application on Heroku. Every time I attempt to push to the master branch, an error message stating "failed to compile node.js" is displayed. Despite following the recommended steps to specify the node ...

Unforeseen Problem: Mocha ES6 Node App Glitch

Encountering an ES6 import issue in Mocha test cases currently. Even after attempting to add the latest Babel and presets, the issue remains unresolved. Various solutions have been tested but none seem to fix the problem. This snippet shows my package.jso ...

Error Encountered: AJAX Request Failed with 400 Bad Request

I've been using mithril.js to communicate with my node back-end. I followed the documentation and added an AJAX request, but there seems to be limited information available on mithril. Encountered Error: mithril.js:2130 POST http://localhost:3000/a ...

The body function in Express-validator is not working as expected

Despite following the example provided in the documentation, I am facing difficulties getting express-validator to work properly. The error message "uncaughtException: body is not a function" is appearing, even though I am using express-validator version 5 ...