Steps for removing temporary files with multer

My Node.js application has a feature that allows users to upload files, and the permissions are enforced using Express middleware with the help of multer.

The usual route first authenticates the user, checks if they have the necessary permission, and then processes the file import. Here's an example:

router.post('/:id/import', passport.authenticate('jwt', { session: false }), permit('admin'), function(req, res, next) {
    MyClass.doImport(req.file.path).then(function(result) {
        res.json(result);
    }).catch(function(error) {
        res.status(500).json(error);
    });
});

Everything works smoothly when there are no errors, and the imported file gets deleted afterwards. However, in case of any errors (such as unauthorized access), the uploaded file remains on the disk.

I want to prevent the creation of any file on disk until all the permission checks by middleware are successfully completed. I've attempted placing multer at the end of the middleware chain like this:

var app = express();

app.use( // ...

app.use(passport.initialize());
app.use(multer({dest:'./tmp/'}).single('file'));

However, even on an authentication error, a file still gets created in the 'tmp' directory.

Is there a way to delay the file creation until all other middleware processes have finished successfully?

If not feasible, can I introduce a new middleware function that runs only if there is a file attachment and an error occurs further up the chain?

Answer №1

Make sure to reposition your multer middleware so that it is only executed right before the specified route handler(s). By doing this, you can prevent any lingering temporary files in case another middleware rejects the request. Here's an example:

function isAuthenticatedUser(req, res, next) {
  if (req.isAuthenticated())
    return next();
  res.redirect('/');
}
var uploadFile = multer({dest:'./tmp/'}).single('file');

var app = express();
// ...
app.use(passport.initialize());
// ...
app.put('/upload', isAuthenticatedUser, uploadFile, function(req, res) {
  // access `req.file`
});

Answer №2

If you're looking to automate the task of deleting temporary files and folders regularly, one approach is to utilize a combination of the cron module along with the 'fs' module. Simply insert the provided code snippet into your app.js file.

var fs = require('fs');
var CronJob = require('cron').CronJob;
var temp_folder_path = path.join(__dirname, 'public', 'uploads');

     /*
        Seconds: 0-59
        Minutes: 0-59
        Hours: 0-23
        Day of Month: 1-31
        Months: 0-11
        Day of Week: 0-6 // 0 = Sunday
       * cronjob for deleting temp files from public/upload folders
       * this cronjob runs from Monday through Friday at midnight 12:00 
    */
    new CronJob('00 00 00 * * 1-5', function () {
    console.log('deleting all temporary file from public/uploads/*');
    deleteFolderRecursive(temp_folder_path)
}, null, true, 'America/Los_Angeles');


// Used for deleting all files and sub-folders from 'public/upload/*'
// Multer : stores temporary files in this folder
var deleteFolderRecursive = function (path) {
    if (fs.existsSync(path)) {
        fs.readdirSync(path).forEach(function (file, index) {
            var curPath = path + "/" + file;
             if (fs.lstatSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
                fs.rmdirSync(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
    }
};

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

Access the folder in Command Prompt along with the directory of the present folder

Whenever I click on the "Open in Command Prompt" option within Visual Studio Code for the selected folder (C:\playground\ng2\app), it should open up in the command line. However, when I check the path in the command prompt, it only displays ...

Updating a single .jshintrc option for a folder

My project has a .jshintrc file at the root, containing the following settings: { "node": true, "smarttabs": true, "undef": true, "unused": true } While these settings work well for node-related code in my project, they are not suitable for brows ...

In search of a fresh and modern Facebook node template

I've been on the hunt across the internet for a quality node.js Facebook template, but all I seem to stumble upon is this https://github.com/heroku/facebook-template-nodejs. It's okay, but it's built using express 2.4.6 and node 0.6.x. I wan ...

EventEmitter - Unable to listen for an event

Hello all! I am facing an issue with implementing the observer pattern in my application. The problem is that the subscribers are unable to listen to events. When a function (useEvent.js) triggers an event, nothing seems to happen. Below are the snippets ...

The issue of the state not persisting persists after verifying the jwt

When a user logs in on the frontend, this function is used to manage their session. The userData state's values are reset to undefined if the user navigates to a different page on the site. An API link "http://localhost:5000/users/isTokenValid" is cal ...

Troubleshooting: Node.js Express Server GET Handler Failing to Function

Recently, I've been attempting to build a GET request handler in Express.js. Here's the snippet of code I've put together: // include necessary files and packages const express = require('./data.json'); var app = express(); var m ...

Encountering a React Express Heroku 503 error when trying to send data through

After successfully running my app locally, I encountered 503 errors for the post routes when deploying to Heroku. Interestingly, the GET routes are functioning properly - particularly the one required for Google OAuth login and the logout route. Any assist ...

Get the csv document from the backend

I am currently working on generating a CSV file, inserting data into it, and then downloading it from the browser. The process involves creating the CSV file in the backend using Express.js and sending the download link to the frontend built with React.js. ...

Error occurred when attempting to send a POST request to the server using AJAX and data did

When I try to send form data using a POST request via AJAX, I am encountering an issue. The data being sent seems complete when I console it in the AJAX call, but on the server side, parts of the object appear to be missing and the data is getting cut off. ...

having difficulty altering a string in EJS

After passing a JSON string to my EJS page, I noticed that it displays the string with inverted commas. To resolve this issue, I am looking for a way to eliminate the inverted comma's and convert the string to UPPERCASE. Does anyone know how to achiev ...

Resolve the "kexec" malfunction obstructing the successful execution of "npm install" for packages like WebPack in the "node_modules" directory following an upgrade to node versions 12, 13, or 14

After upgrading from "node" to "node 14", I attempted an "npm install" but encountered a failure due to the compilation error of "kexec" (also known as "node-kexec") which is a requirement for WebPack. The error messages received were: npm ERR! path /User ...

Unable to retrieve the body from an HTTP POST request in NextJS

Currently stuck and seeking assistance to uncover the missing piece that is preventing progress. The goal is to obtain access to the body of a POST request, as demonstrated on this page from Next.js: https://nextjs.org/docs/pages/building-your-application ...

Jade block refuses to render

I seem to be overlooking a small detail. Currently, I am experimenting with jade templates in express and trying to utilize blocks and extensions. However, my block does not seem to be functioning correctly. Below are the jade templates I am working with: ...

a function that is not returning a boolean value, but rather returning

There seems to be a simple thing I'm missing here, but for the life of me, I can't figure out why the function below is returning undefined. var isOrphanEan = function isOrphanEan (ean) { Products.findOne({ 'ean': ean }, func ...

sustain inquiring process while invoked by node interpreter directive

Here is a function that I am working with: const runInteractive = (rows, dups) => { const keys = new Set(dups); const questions = _(rows) .filter(row => keys.has(row.key)) .groupBy(row => row.key) .map((rows, key) => ({ ...

Why isn't the transparency feature in graphicsmagick working?

Currently, I am utilizing the graphicsmagick npm package which can be found at https://www.npmjs.com/package/gm. In my attempt to write a piece of code similar to the one below, I am struggling to make it function properly with stream. The image file myimg ...

Having trouble with the $push operator in Mongo DB?

I am facing an issue while attempting to store data in an array within an object in a Mongo model by utilizing the req.params method. Unfortunately, I encounter the following error: MongoError: cannot use the part (friends of friends.username) to traverse ...

AngularJS session timeout refers to the period of inactivity before

Would it be possible to handle user sessions with Angularjs? For example: Setting session timeout for idle systems. Displaying alerts (popup with message asking if the user wants to continue - yes or no) when the session is about to expire, with the optio ...

What is the alternative method to adjust the npm prefix without using configuration?

After mistakenly setting the npm prefix to a non-existent location, I'm wondering if there's a configuration file that can be modified to revert this change. Currently, my options seem limited to: Fully uninstalling Node (npm not responding af ...

Updating model names and table names with Loopback and MySQL in Node.js can easily be done by following a few

Utilize Loopback(nodejs) in conjunction with mysql. I am looking to alter the model name and table name to something different. I prefer not to display the table name in the API URL. New table name = 'super_member' New model name = 'memb ...