Uploading files using Multer, without knowing the their fieldname
Asked Answered
V

5

14

After looking at this article: http://lollyrock.com/articles/express4-file-upload/

I've realized that Multer used to allow file uploads when you did not know the name of the form field being uploaded. For example, if you look at the "using Multer" section of the article, you'll see that the writer does not use either .single(), .array(), or .fields() when calling app.use(). If you do that with the current version of Multer, you'll get the error TypeError: app.use() requires middleware functions.

While I have a slight idea as of how to use .single(), .array(), or .fields(), my current project requires that I send an unspecific amount of files to my server (may be a series of .png or .log files). Therefore, I don't know what the field names will be beforehand.

Doing that was easy with the version of Multer used in the article (0.1.6), but seems impossible when attempting it in the current version of Multer (1.0.3) since you need to specify the form fieldnames.

Alternatively, finding a full guide of Multer online has been a challenge, since the best one seems to be the Readme of the GitHub repo, and that one seems to be lacking. Maybe the answers that I'm looking for will be in a guide somewhere.

Thank you!

Vivien answered 7/8, 2015 at 15:16 Comment(6)
Why are you not in control of the field name? Obviously you're not in control of the filename. Is that what you meant?Analisaanalise
I did mean the field name. And I'm not in control of the field name because I am not sure how many files I'd be receiving. Edit: I am looking into .fields() closer, that might be the answer that I'm looking for. But I need to control filedname for that.Vivien
If you use multer().array('foo') then you can have as many files as you want, as long as the field name for each file is the same (foo). Surely requiring that the client uses the same field name for each file is not out of the question?Analisaanalise
That might be something that I'll need to enforce, but it is be doable.Vivien
@SammyI. Multer is specifically programmed so that you need to know the fields before-hand because of security reasons outlined in Issue 133. While we maybe could add a .any() method I would prefer to leave that out. It seems like the way that @Analisaanalise proposed is the way to go. Is there some reason why that would not work for you?Entente
@LinusUnnebäck After some talking, we decided for going forward using Multer's method. Now the fields need to be known beforehand.Vivien
S
27

Just use multer.any() and you get those files in request.files.

var router   = express.Router();
var app      = express();    
var _fs      = require("fs");
var _config  = require("./config");
var multer   = require("multer");
var upload   = multer({ dest: _config.tempDir })

app.use(bodyParser.urlencoded({extended:true}));

app.post("/api/files", upload.any(),  function(req, res){             
    var files = req.files;
   if(files){
        files.forEach(function(file){

            //Move file to the deployment folder.
            var newPath =  _utils.DetermineFileName(file.originalname, _config.destinationDir);
            _fs.renameSync(file.path, path.join(_config.destinationDir, newPath));
            var newFileName = path.basename(newPath);
            console.log(newFileName + ' saved at '  + _config.destinationDir );
        });
    }
};
Sociability answered 22/6, 2016 at 5:5 Comment(2)
This does't works in typescript. I am trying similar code. When tried to assign req.files to array variable it errors out as shown -------------- Type 'File[] | { [fieldname: string]: File[]; }' is not assignable to type 'File[]'. Type '{ [fieldname: string]: File[]; }' is missing the following properties from type 'File[]': length, pop, push, concat, and 26 more.ts(2322) --------------------- also, files.forEach doesn't work as files is not an array. Anybody knows any solution around this problem?Krystenkrystin
I've got the solution const filesArr: any | Express.Multer.File[] = req.files; Then check if(Array.isArray(filesArr)){ // your code here } then code does not errors out. ThanksKrystenkrystin
M
4
multer().any();

Not tested it, but it should work.

Melbourne answered 21/1, 2016 at 13:35 Comment(0)
S
1

Just use .array('name') now you can receive as many files which have same field as name also define this anme on your client side as arguments i am using this same approach and it works completely fine if there are still any query you are getting feel free to comment :)

Sall answered 23/10, 2015 at 21:23 Comment(0)
P
0

Bit of a hack but works with Multer v1.1.0:

multer().single("undefined")
Pithy answered 7/1, 2016 at 6:5 Comment(0)
R
0

When you create a web form or send a request with FormData, you can use the same field name more than once.

If you use multer(opts).array('foo', max) where foo is the field name, you can add as much as max files using the same field name.

For more tuning options, you can use opts.limits

An example of a customizable middleware using multer:

module.exports = (options) => {
  const params = Object.assign({
    destination: 'uploads/',
    fieldName: 'foo',
    limitFiles: 5, // default: max 5 file
    limitFileSize: 52_428_800 // default: max 50 MiB per file
  }, options)

  return multer({
    dest: params.destination,
    limits: {
      files: params.limitFiles,
      fileSize: params.limitFileSize
    }
  }).array(params.fieldName, params.limitFiles)
}
Raseta answered 21/9, 2023 at 16:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.