Change filename when using express/multer
Asked Answered
L

5

14

I'm having trouble uploading a pdf, when I upload it (I'm using ng-file-upload) the file json that reachs express.js is:

{ fieldname: 'file',
  originalname: 'db.pdf',
  encoding: '7bit',
  mimetype: 'application/pdf',
  destination: './client/public/docs/transactions/',
  filename: '8a3fe7cb7369d9cffa8e17b162ec3d6b',
  path: 'client\\public\\docs\\transactions\\8a3fe7cb7369d9cffa8e17b162ec3d6b',
  size: 9179145 }

I'd like to change the name to a property that I send from angular to express, here's all the setup:

html element:

<div ngf-select="vm.uploadPdf($file, $errFiles)"
     ngf-pattern="'.pdf'"
     accept="application/pdf" ngf-max-size="20MB">Select ...
</div>

angular func uploadPdf (ctrl as vm):

function uploadPdf( file, errFiles ) {
    vm.pdf = file;
    vm.errorFile = errFiles && errFiles[ 0 ];

    if ( vm.pdf ) {
        Upload
            .upload( {
                url: '/upload',
                data: {
                    file: vm.pdf,
                    new_file_name: vm.new_name//this is the filename I want
                }
            } )
            .then(
                function ( response ) {
                    $timeout( function () {
                        vm.pdf.result = response.data;
                    } );
                }, function ( response ) {
                    if ( response.status > 0 ) {
                        vm.errorQuedanPdfUpload = response.status + ': ' + response.data;
                        console.log( vm.errorQuedanPdfUpload );
                    }
                }
            );
    }
}

express:

var express = require( 'express' ),
    router  = express.Router(),
    util    = require( 'util' ),
    multer  = require( 'multer' );

var storage = multer.diskStorage(
    {
        destination: './uploads/',
        filename: function ( req, file, cb ) {
            //req.body is empty...
            //How could I get the new_file_name property sent from client here?
            cb( null, file.originalname );
        }
    }
);

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

router.route( '/upload' )
    .post( upload.single( 'file' ), post );

function post( request, response ) {

    response.json( { message: 'Files Uploaded!' } );

}
Lublin answered 2/12, 2015 at 5:24 Comment(3)
There is no problem with angular. Multer does not store extension on file upload.Billion
Check this: github.com/expressjs/multer/issues/170Billion
Use answer given by ricardomoura in above link to do achieve your taskBillion
K
23
var express = require( 'express' ),
    router  = express.Router(),
    util    = require( 'util' ),
    multer  = require( 'multer' );

var storage = multer.diskStorage(
    {
        destination: './uploads/',
        filename: function ( req, file, cb ) {
            //req.body is empty...
            //How could I get the new_file_name property sent from client here?
            cb( null, file.originalname+ '-' + Date.now()+".pdf");
        }
    }
);

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

router.route( '/upload' )
    .post( upload.single( 'file' ), post );

function post( request, response ) {

    response.json( { message: 'Files Uploaded!' } );

}
Knotweed answered 2/9, 2017 at 10:26 Comment(3)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Nickinickie
if I have multiple files, does multer iterate over all the files and change the filenames to the original names ?Annuity
If you leave out destination, the file gets saved to /var/folders/p5/. Is that still on the server, or is that on the end user's machine?Gunrunning
B
3
var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads/')
  },
  filename: function (req, file, cb) {

      cb(null,  file.originalname );

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

Configure like this in your express

Billion answered 2/12, 2015 at 5:40 Comment(3)
the filename that I want is sent from the client, so how do I get it in the filename function of diskStorage?Lublin
And make sure your uploads directory, does not have similar filename upload, otherwise your might overwrite existing file.Billion
No, I don't want the original name, I want to set the name as: filename: vm.code check out the uploadPdf funcLublin
M
0

In Angular you need to move new_file_name to be above file in data as follows:

    Upload
        .upload( {
            url: '/upload',
            data: {
                new_file_name: vm.new_name, //this is the filename I want
                file: vm.pdf
            }
        } )

Basically browser needs to send that data before the file ... Better explanation can be found here: https://github.com/expressjs/multer/issues/134

Mop answered 31/12, 2015 at 6:58 Comment(0)
H
0

This is how my upload configuration looks:

const storage = multer.diskStorage({
    destination: (req, file, callBack) => {
        callBack(null, "your_upload_path");
    },
});
const upload = multer({ storage });

This is how I post on the server:

server.post(
    "your_url",
    upload({
        fileName: (req, file) => {
            return `${req.body.your_desired_field_name}_${file.originalname}`;
        },
    }).single("your_file_key_name"),
    async (req, res) => {
        try {
            // your code
        } catch (err) {
            res.status(500).send(err);
        }
    }
);
Hydrophobic answered 6/9, 2023 at 6:19 Comment(0)
M
0

Here is my solution on how i change the file name on Multer: I attach the file name i want into the header, and create a middleware that will extract the file name and assigned that to req.customFileName

Here is my my code at frontend

const customName = "MyCustomName"
const extName = imageFile.name.split(".").pop();

Headers:

 headers: {
              filename: `${customName}.${extName}`,
            },

File name extract middleware on your backend:

const extractFileName = (req, res, next) => {
  req.customFileName = req.headers["filename"];
  next();
};
module.exports = extractFileName;

Apply this middleware in your code like this

var express = require( 'express' ),
router  = express.Router(),
util    = require( 'util' ),
multer  = require( 'multer' );
const extractFileName = require("../middleware/extractFileName");
var storage = multer.diskStorage(
    {
        destination: './uploads/',
        filename: function ( req, file, cb ) {
            //req.body is empty...
            //How could I get the new_file_name property sent from client here?
            cb( null, req.customFileName); //You get your file name here
        }
    }
);

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

router.route( '/upload' )
    .post( extractFileName, upload.single( 'file' ), post ); //apply your custom middleware before using multer

function post( request, response ) {

    response.json( { message: 'Files Uploaded!' } );

}

Hope this helps

Marianamariand answered 22/10, 2023 at 17:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.