GithubHelp home page GithubHelp logo

multer's Introduction

Multer Build Status NPM version js-standard-style

Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on top of busboy for maximum efficiency.

NOTE: Multer will not process any form which is not multipart (multipart/form-data).

Translations

This README is also available in other languages:

Installation

$ npm install --save multer

Usage

Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.

Basic usage example:

Don't forget the enctype="multipart/form-data" in your form.

<form action="/profile" method="post" enctype="multipart/form-data">
  <input type="file" name="avatar" />
</form>
const express = require('express')
const multer  = require('multer')
const upload = multer({ dest: 'uploads/' })

const app = express()

app.post('/profile', upload.single('avatar'), function (req, res, next) {
  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any
})

app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
  // req.files is array of `photos` files
  // req.body will contain the text fields, if there were any
})

const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
  // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
  //
  // e.g.
  //  req.files['avatar'][0] -> File
  //  req.files['gallery'] -> Array
  //
  // req.body will contain the text fields, if there were any
})

In case you need to handle a text-only multipart form, you should use the .none() method:

const express = require('express')
const app = express()
const multer  = require('multer')
const upload = multer()

app.post('/profile', upload.none(), function (req, res, next) {
  // req.body contains the text fields
})

Here's an example on how multer is used an HTML form. Take special note of the enctype="multipart/form-data" and name="uploaded_file" fields:

<form action="/stats" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <input type="file" class="form-control-file" name="uploaded_file">
    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
    <input type="submit" value="Get me the stats!" class="btn btn-default">
  </div>
</form>

Then in your javascript file you would add these lines to access both the file and the body. It is important that you use the name field value from the form in your upload function. This tells multer which field on the request it should look for the files in. If these fields aren't the same in the HTML form and on your server, your upload will fail:

const multer  = require('multer')
const upload = multer({ dest: './public/data/uploads/' })
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
  // req.file is the name of your file in the form above, here 'uploaded_file'
  // req.body will hold the text fields, if there were any 
  console.log(req.file, req.body)
});

API

File information

Each file contains the following information:

Key Description Note
fieldname Field name specified in the form
originalname Name of the file on the user's computer
encoding Encoding type of the file
mimetype Mime type of the file
size Size of the file in bytes
destination The folder to which the file has been saved DiskStorage
filename The name of the file within the destination DiskStorage
path The full path to the uploaded file DiskStorage
buffer A Buffer of the entire file MemoryStorage

multer(opts)

Multer accepts an options object, the most basic of which is the dest property, which tells Multer where to upload the files. In case you omit the options object, the files will be kept in memory and never written to disk.

By default, Multer will rename the files so as to avoid naming conflicts. The renaming function can be customized according to your needs.

The following are the options that can be passed to Multer.

Key Description
dest or storage Where to store the files
fileFilter Function to control which files are accepted
limits Limits of the uploaded data
preservePath Keep the full path of files instead of just the base name

In an average web app, only dest might be required, and configured as shown in the following example.

const upload = multer({ dest: 'uploads/' })

If you want more control over your uploads, you'll want to use the storage option instead of dest. Multer ships with storage engines DiskStorage and MemoryStorage; More engines are available from third parties.

.single(fieldname)

Accept a single file with the name fieldname. The single file will be stored in req.file.

.array(fieldname[, maxCount])

Accept an array of files, all with the name fieldname. Optionally error out if more than maxCount files are uploaded. The array of files will be stored in req.files.

.fields(fields)

Accept a mix of files, specified by fields. An object with arrays of files will be stored in req.files.

fields should be an array of objects with name and optionally a maxCount. Example:

[
  { name: 'avatar', maxCount: 1 },
  { name: 'gallery', maxCount: 8 }
]

.none()

Accept only text fields. If any file upload is made, error with code "LIMIT_UNEXPECTED_FILE" will be issued.

.any()

Accepts all files that comes over the wire. An array of files will be stored in req.files.

WARNING: Make sure that you always handle the files that a user uploads. Never add multer as a global middleware since a malicious user could upload files to a route that you didn't anticipate. Only use this function on routes where you are handling the uploaded files.

storage

DiskStorage

The disk storage engine gives you full control on storing files to disk.

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/tmp/my-uploads')
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
    cb(null, file.fieldname + '-' + uniqueSuffix)
  }
})

const upload = multer({ storage: storage })

There are two options available, destination and filename. They are both functions that determine where the file should be stored.

destination is used to determine within which folder the uploaded files should be stored. This can also be given as a string (e.g. '/tmp/uploads'). If no destination is given, the operating system's default directory for temporary files is used.

Note: You are responsible for creating the directory when providing destination as a function. When passing a string, multer will make sure that the directory is created for you.

filename is used to determine what the file should be named inside the folder. If no filename is given, each file will be given a random name that doesn't include any file extension.

Note: Multer will not append any file extension for you, your function should return a filename complete with an file extension.

Each function gets passed both the request (req) and some information about the file (file) to aid with the decision.

Note that req.body might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server.

For understanding the calling convention used in the callback (needing to pass null as the first param), refer to Node.js error handling

MemoryStorage

The memory storage engine stores the files in memory as Buffer objects. It doesn't have any options.

const storage = multer.memoryStorage()
const upload = multer({ storage: storage })

When using memory storage, the file info will contain a field called buffer that contains the entire file.

WARNING: Uploading very large files, or relatively small files in large numbers very quickly, can cause your application to run out of memory when memory storage is used.

limits

An object specifying the size limits of the following optional properties. Multer passes this object into busboy directly, and the details of the properties can be found on busboy's page.

The following integer values are available:

Key Description Default
fieldNameSize Max field name size 100 bytes
fieldSize Max field value size (in bytes) 1MB
fields Max number of non-file fields Infinity
fileSize For multipart forms, the max file size (in bytes) Infinity
files For multipart forms, the max number of file fields Infinity
parts For multipart forms, the max number of parts (fields + files) Infinity
headerPairs For multipart forms, the max number of header key=>value pairs to parse 2000

Specifying the limits can help protect your site against denial of service (DoS) attacks.

fileFilter

Set this to a function to control which files should be uploaded and which should be skipped. The function should look like this:

function fileFilter (req, file, cb) {

  // The function should call `cb` with a boolean
  // to indicate if the file should be accepted

  // To reject this file pass `false`, like so:
  cb(null, false)

  // To accept the file pass `true`, like so:
  cb(null, true)

  // You can always pass an error if something goes wrong:
  cb(new Error('I don\'t have a clue!'))

}

Error handling

When encountering an error, Multer will delegate the error to Express. You can display a nice error page using the standard express way.

If you want to catch errors specifically from Multer, you can call the middleware function by yourself. Also, if you want to catch only the Multer errors, you can use the MulterError class that is attached to the multer object itself (e.g. err instanceof multer.MulterError).

const multer = require('multer')
const upload = multer().single('avatar')

app.post('/profile', function (req, res) {
  upload(req, res, function (err) {
    if (err instanceof multer.MulterError) {
      // A Multer error occurred when uploading.
    } else if (err) {
      // An unknown error occurred when uploading.
    }

    // Everything went fine.
  })
})

Custom storage engine

For information on how to build your own storage engine, see Multer Storage Engine.

License

MIT

multer's People

Contributors

3imed-jaberi avatar axelpale avatar carlosstenzel avatar cgmartin avatar crandmck avatar eugene0928 avatar fishrock123 avatar framp avatar fsanzv avatar gireeshpunathil avatar hacksparrow avatar hcz avatar jonchurch avatar jpfluger avatar khacpv avatar linusu avatar maxcnunes avatar ostefanini avatar pdehaan avatar puhsiu avatar scottbouloutian avatar stefkors avatar tmarshall avatar trott avatar tsando avatar turakvlad avatar vitorribeiro7 avatar wowzzangga avatar x-n0 avatar zengming00 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multer's Issues

Error - csurf with multer

Hello, im using csrf module (csurf) but when im uploading...

Error: invalid csrf token
   at verifytoken (D:\nodejs\node_modules\csurf\index.js:234:13)
   at csrf (D:\nodejs\node_modules\csurf\index.js:94:7)
   at Layer.handle [as handle_request] (D:\nodejs\node_modules\express\lib\router\layer.js:76:5)
   at trim_prefix (D:\nodejs\node_modules\express\lib\router\index.js:263:13)
   at D:\nodejs\node_modules\express\lib\router\index.js:230:9
   at Function.proto.process_params (D:\nodejs\node_modules\express\lib\router\index.js:305:12)
   at D:\nodejs\node_modules\express\lib\router\index.js:221:12
   at Function.match_layer (D:\nodejs\node_modules\express\lib\router\index.js:288:3)
   at next (D:\nodejs\node_modules\express\lib\router\index.js:182:10)
   at methodOverride (D:\nodejs\node_modules\method-override\index.js:77:5)`

var product=config.upload;

 uri.route('/up').get(function (req,res,next) {
              res.render('upload',{
                csrf  : req.csrfToken()
              });
              res.end();
      }).post(product,function  (req,res,next) {
        console.log('IN POST (/upload)');
        console.log(req.body)
        var filesUploaded = 0;
        if ( Object.keys(req.files).length === 0 ) {
            console.log('no files uploaded');
        } else {
            console.log(req.files)

            var files = req.files.file1;
            if (!util.isArray(req.files.file1)) {
                files = [ req.files.file1 ];
            } 

            filesUploaded = files.length;
        }
        res.json({ message: 'Finished! Uploaded ' + filesUploaded + ' files.  Route is /upload' });
      });

🔨

Writing files to the disk

Currently files seem to always be written to disk, although with the new inMemory option this my not be needed. Writing files to the disk just to delete them again is both useless and unnecessary. Therefore a "writeToDisk" option would be useful.

I suggest to use !inMemory as the standard value for this option, because this is (from my perspective) the expected behavior.

Using multer inside controllers/models

Folks,

Host can I invoke the onFileUploadComplete method from my controller?

server.js

server.use(multer({ dest: '/tmp'}));
server.post('/users/:id/avatar', avatar.post);

avatar.js

post: function (req,res) {
    var image = req.files;
    console.log (req.files);

    onFileUploadComplete: function (file) {
        console.log(file.fieldname + ' uploaded to  ' + file.path);
       ....
         responses.Success('wroteToDB',res);
    }
},

Thanks!

regards limits in multer

when we upload file thats bigger than "fileSize" limit. multer can store that file with new limited size. How we get limit of file exceed ??
And one simple one, what is the unit type we specify in limits ?

Multer emits 'end' and chains to the next middleware prematurely when parsing file parts

Multer uses the busboy 'end' event to fire its own 'onParseEnd' event and cede control to the next registered middleware in the chain. The problem is that busboy fires this event when it is finished parsing the form data and firing events related to the parts it encounters but hasn't necessarily finished writing out any files attached to the form it's just parsed.

Downstream middleware modules that immediately open these files see inconsistent file contents (truncated, in other words) depending on when they open the files. Sometimes the files are written out in time for the next middleware to be able to use them completely, sometimes not.

Here is additional detail from the busboy issue list about this problem in general, and suggestions for fixes: mscdex/busboy#1. To be clear, it is not currently considered a busboy problem fixable within busboy itself, but rather an API usage issue.

Finalize the reception on client side

Hi,

Thanks for this great module that might save me a lot of time. Unfortunately I'm new to all of this and it wasn't clear to me that I had to send a status code 200 to make the client enter its success callback.

Maybe a line about that and an example would be nice.

I am not too sure but something like that :

app.post "/api/files/upload", (req, res) ->
   console.log ('upload done for ' + req.files.file.name)
   res.setHeader "Content-Type:", "application/json"
   res.send 200, {myFileReference: req.files.file.name}

Nicolas

File upload sometimes hangs - multer, busboy, or something else?

HI!

I encountered some strange problem while using multer - sometimes it hangs while uploading the file.

When I am testing this behavior on my Ubuntu it succeeds every time, but when I switch to development server it hangs quite often.

I compared the behavior on both environments and added some basic printouts for troubleshooting:

app.use(multer({
  dest: './uploads/',
  rename: function (fieldname, filename) {
    return filename.replace(/\W+/g, '-').toLowerCase();
  },
  onFileUploadStart: function (file) {
    process.stderr.write('Uploading file..........');
  },
  onFileUploadComplete: function (file) {
    process.stderr.write('done\n');
  },

...

}));

On development server Uploading file......... is printed in the console but done doesn't show up - which suggests it can be multer or busboy issue.

Full code in which I am using multer can be found here:
https://github.com/aplikacjespoleczne/WizualizacjaBudzetu

Also for troubleshooting I've added the simmilar logging to the multer code (in index.js) :

        fileStream.on('data', function(data) {
          console.log('Next part received!');        // ADDED
          if (data) { file.size += data.length; }
          // trigger "file data" event
          if (options.onFileUploadData) { options.onFileUploadData(file, data); }
        });

And the difference between Ubuntu and development server is the last chunk of data. In both environments Next part received! shows up but on development server done doesn't - which may suggest that the 'finish' event is not emitted.

Can it be multer or busboy? Can you give me some advice where to look further? What else could I trace?

Thanks!

Access to state during event flow

Hi,

First off, great plugin, using it for a POC and does what it says on the tin!

Just a question in relation to how I can access output generated as part of the multer step or to pass objects into it!

For example;

  1. User posts many files to an api/upload endpoint
  2. Mutler kicks in and as part of the onFileUploadComplete event, triggers the images to be compressed
  3. If all the events in Multer are successful, the user receives a valid 200 with a JSON response
  4. Mongdb is updated with the results and images are both stored in static directory and in database as a base64 string

However, as part of the onFileUploadComplete event i need the output generated to be added to an existing table or at least added to already created object that will be saved when Multer is completed.

Your advice would be appreciated on how to either store the compressed image to the db by passing in the new mongo model during the onFileUploadComplete step or by returning the compressed image so that it can be done outside of the Mutler tasks.

J

Large File Handling (eg 2.5 MB file) Slower When InMemory is True

When inMemory is true and file.buffer is larger than 64 Kb, there is an "issue" that I don't think is fixable right now b/c it's the way Node.js currently allocates memory for large buffers. (see StackOverflow and this blog)

In multer/master, I have mocha tests (see test/inmemory.js) that can be used to test this issue. When running, the multi-file upload test take an average of 1 second. Compare this to the write-to-disk multi-file upload taking 100 ms. In local tests, I changed-up my inMemory Buffer code to a writable stream and piped the filestream directly to it but still would get 1 second performance. I don't think my test hardware is to blame (i7-4810MQ w/ 32 Gig RAM on SSDs).

I also ran the tests against the latest node in development 0.11.14 but there's a bug preventing mocha from completing. Need to keep an eye on this b/c TJ wrote "[there's been] significant performance work done in core features (Buffers, TLS, streams)." reference

Hopefully I'm wrong with this issue and someone knowing more about how core streams/Buffers work can suggest ways to improve inMemory performance for large buffers.

Dynamic folder Names would be Nice

Hope all is well and understand you're quite busy. But it would be great if we could pass along req.params to the destination so we could save things in folders based on parameters.

Set different destination path

I'm not getting how to set different destination path for say different routes?
Example : app.post('/api/upload', function (req, res) { // here i want destination as dest: './static/uploads/'

and app.post('/api/pic', function (req, res) { // here i want destination as dest: './static/pic/

and app.post('/api/pdf', function (req, res) { // here i want destination as dest: './static/pdf/'

Body parser array

Hi!

First, congratulations for this middleware, it's awsome and simple!

Look my issue as a improvement for multer.

I have some html inputs and they are in array, for example (in Jade):

input(name="team[0]name")
input(name="team[0]leaderName")

input(name="team[1]name")
input(name="team[1]leaderName")

When I process this code, my response is:

{
    team[0]name: "John",
    team[0]leaderName: "Brad",
    team[1]name: "Mike",
    team[1]leaderName: "Leo"
}

In this case, if the structure of the response was changed to the following structure, would be better?

{
    team: [
        {
            name: "John",
            leaderName: "Brad"
        },
        {
            name: "Mike",
            leaderName: "Brad"
        }
    ]
}

Thanks! (sorry my english)

Error: ENOENT, open 'uploads/xxx'

Sometimes it will throw this error: "Error: ENOENT, open 'uploads/xxx'".
How can I avoid this?

Here is my code:

app.use(multer({
  dest: './uploads/',
  rename: function (fieldname, filename) {
    return filename;
  }
}))

Is inMemory option ready to be published on NPM?

I was attempting to use the inMemory option as described in the documentation, against the latest version on NPM with no success, until I realized that inMemory was fairly new and while available on this repo, it has not been published to NPM yet.

It looks like the latest version on NPM is 0.1.4, while this repo is up to 0.1.6. Are you planning on publishing on NPM soon to make the inMemory feature available without needing to reference a Github commit for installation?

Upload security

This is not an issue with multer directly, but more an issue with applications using multer.

There is little to no mention of any security issues with file uploads handled by multer leading to a lot of example code around the web based off the simple examples in the readme that completely ignore any security issues, notably things like:

var express = require('express')
var multer  = require('multer')

var app = express()
app.use(multer({ dest: './uploads/'}))

app.post('/api/uploads', ...handles maby one expected file...)

The first major issue here is that multer will be executed on any post request, even for post requests that are not expected to handle files, meaning that you could potentially upload files to the server bypassing the upload url if there exists another post url.

This is a major concern as if people are using these examples directly in their code they will be vulnerable to to file upload exploits if they do not already know about them.

The example should probably be changed to app.use('/api/upload', multer({ dest: './uploads/'})) so that multer only handles files to locations that are known to handle uploads.

It also might be worth adding a filter on what files are expected so that the user does not have to worry about unexpected files being uploaded. Something long the lines of:

app.use('/api/uploads', multer({ dest: './uploads', filter: ['someFile']})

so that multer only handles files found in the POST requests someFile variable and rejects/errors for any other files found. This could be partly done by limits.files, but this does not ensure that the expected file ends up in the right variable, and people generally only check for what they are expecting.

Required Event: onFileSizeLimit

Busboy provided fileSizeLimit for limits, and it emit 'limit' event on fileStream when it reach the limit, but on the multer, it doesn't have a listener to this event, which is needed I think.
Or, the file will just stop uploading and left broken without any error when reach the limit, it requires to be handled.
I read your code and add this next to your many fileStream.on():

    fileStream.on('limit', function() {
      if (options.onFileSizeLimit) { options.onFileSizeLimit(); }
    })

I hacked this for I needed right now, please add this to your code and update it later.

InMemory tests failing on v0.11 (Travis / Mocha)

multer/master passes Travis with node v0.10. But does not for v0.11. In mocha tests, the blowups happen on line 64 test/inmemory.js, where the inMemory buffer is compared to the file size.

expect(form.files.small0.buffer.length).to.equal(form.files.small0.size);

form.files.small0.bufferis an object but lacks a.length` property. In fact, instantiating a new buffer from this one

new Buffer(new Buffer(form.files.small0.buffer)

does give me a valid .length property.

Thus, the following test code will work:

if ( form.files.small0.buffer !== undefined ) {
    console.log( new Buffer(form.files.small0.buffer).length);
    form.files.small0.buffer = new Buffer(form.files.small0.buffer);
}
console.log( 'file length=' + form.files.small0.size + '    buffer length = ' + form.files.small0.buffer.length );
expect(form.files.small0.buffer.length).to.equal(form.files.small0.size);

I have verified that index.js does assign a valid file.buffer property before ending the filestream and file.buffer.length is accessible.

FILEEND: file length=1778    buffer length = 1778
ONFINISH: file length=1778    buffer length = 1778

Question(s)

  1. I can't understand why the parameters would be modified between creation and sending? It could be on how v11 receives the request?

Update:

res.send sends req.body and req.files to the server as a JSON object. I suspect the problem is in how the Buffer is (not created) by JSON on receive. But why the different JSON treatment between 0.10 and 0.11? Unless someone has some ideas, I'll go hunting for that after I get something to eat.

Update 3

That's exactly what's happening. JSON.parse() is done differently in v0.11. It can be tested for in multer by diving down into node_modules/express/lib/response.js and at line 229, just after var body = JSON.stringify(val, replacer, spaces);, insert the following:

var restored = JSON.parse(body);

if ( restored.files !== undefined ) {
    console.log( 'RESPONSE A: file length=' + val.files.small0.size + '    buffer length = ' + val.files.small0.buffer.length );
    console.log( 'RESPONSE B: file length=' + restored.files.small0.size + '    buffer length = ' + restored.files.small0.buffer.length );
}

Dynamically changing destination folder name

Is it possible to dynamically change the destination folder name depending on the field name? I made a quick test which failed

app.use(multer({
  dest: './uploads/',
  rename: function (fieldname, filename) {
      if(fieldname == 'avatar_file'){
          return filename.replace(/\W+/g, '-').toLowerCase() + Date.now()
      } else {
          return 'avatars/' + filename.replace(/\W+/g, '-').toLowerCase() + Date.now()
      }
  }
}))

Thanks

On aborting an upload

Is there a way of catching aborting event (e.g. user shut down the browser while uploading)?

Upload path : dynamic

Is it possible to assign an upload path on user base? (a kind of route per user)

Thanks
Lorenzo

Async call in onFileUploadStart

Currently there exists the ability to stop an upload by returning false.

onFileUploadStart: function (file) {
  if (file.originalname == 'virus.exe') return false;
}

I'm suggesting the ability to provide a function with two arguments where the second argument is a callback. If cb(false) is called the file is not uploaded.

onFileUploadStart: function (file, cb) {
  somethingAsync(function(err) {
    if(err) return cb(false);
    // Do something
    return cb();
  });
}

There may be a better away of approaching this, or a reason this wouldn't work. Input is appreciated. Otherwise I can work on submitting a PR.

No simple way to tell the client if an error occured

All of the error handling functions, onFileSizeLimit, onError etc... have no way of either telling the client that an error has happened or passing the fact an error happened to the next middle ware:

  router.use('/uploads', multer({
    dest: './uploads',
    limits: { files: 2 },
    onFilesLimit: function () {
      // No way to add to the request that an error occurred, or respond to the client
   }
  });

  router.post('/uploads', function(req, res) {
    // Cannot tell that any of the limits has been reached so cannot inform the client
  });

You probably don't want to respond to the client directly when a limit has been hit, but you should at least be able to tell that an error occurred later on.

Something along the lines of:

  router.use('/uploads', multer({
    dest: './uploads',
    limits: { files: 2 },
    onFilesLimit: function (file_data) {
      file_data.files_limit_reached = true;
   }
  });

  router.post('/uploads', function(req, res) {
    if (file_data.files_limit_reached) {
        res.json({ error: "file limit reached" });
    }
  });

So that rather then removing the files that have hit an error or exceeded a limit they are flagged with an error message.

Set different upload directory based on user id [question]

Hello there.
In my web app all the users have a unique id, and i want the uploaded images to be stored in a directory named based on their id.

Example:

.public/uploads/3454367856437534

Here is a part of my routes.js file:


// load multer to handle image uploads
var multer = require('multer');
var saveDir = multer({
dest: './public/uploads/' + req.user._id, //error, we can not access this id from here
onFileUploadStart: function (file) {
return utils.validateImage(file); //validates the image file type
}
});

module.exports = function(app, passport) {

app.post('/', saveDir, function(req, res) {
id : req.user._id, //here i can access the user id
});
});

}

How can i access the "req.user._id"

outside of the "function(req,res)"

So i can use it with multer to generate the proper directory based on the id?

In other words, i want to handle the destination of the uploaded file in callback function (req,res)

readme.md has some problems

onFilesLimit()

Event handler triggered when the number of files exceed the specification in the limit object. No more files will be parsed after the limit is reached.

Example:

onFilesLimit = function() {
console.log('Crossed file limit!');
};
onFieldsLimit()

Event handler triggered when the number of fields exceed the specification in the limit object. No more fields will be parsed after the limit is reached.

Example:

onFilesLimit = function() {
console.log('Crossed fields limit!');
};
onPartsLimit()

Event handler triggered when the number of parts exceed the specification in the limit object. No more files or fields will be parsed after the limit is reached.

Example:

onFilesLimit = function() {
console.log('Crossed parts limit!');
};

Supporting PUT requests?

In multer/Express 4 support for PUT requests has been removed. Multer should parse PUT requests as well as POST ones.

inMemory Question

If inMemory is set to true, when or how would the file be removed from memory?

(Sorry, if it's a dumb question.)

Different destination folders?

Hi guys! Well, imagine a scenario where I have two forms, FormA and FormZ.

FormA the destination folder is ./uploads/customers

FormZ the destination folder is ./uploads/products

What is the best way to save my uploaded files in separate folders?

Error: "Cannot switch to old mode now."

I'm using node.js version v0.10.28, ExpressJS v4.3.0 and Multer v0.0.7

When I send any files to a route which accepts multipart form data I get the error above. It was working perfectly fine, I'm not sure what's changed. 😕

Request occasionally hangs if files limit is exceeded

The following code works if you try to upload 2 or less files but the request hangs if you upload 3 or more files.

var express = require('express');
var multer = require('multer');
var app = express();

app.use('/upload', multer({
    dest: 'upload',
    limits: { files: 2 }
}));

app.post('/upload', function(req, res) {
  res.json({files: req.files});
});

var server = app.listen(3001, function() {
  console.log('Express server listening on port ' + server.address().port);
});

req.files.fieldname is not an array

Hi,
I'm really new to all this so I apologize if this is a really stupid question
Is there any particular reason why
if (req.files[field].length === 1) {
req.files[field] = req.files[field][0];
}
is included in the onFinish function?

This is causing the length attribute to become undefined.
This is a small issue as I use the length to traverse through the entire array in case multiple files are sent.

Why the decision to not add blank submitted fields to req.body?

Am current switching my project from using connect-multiparty to multer which in general was pretty painless except for one issue that I have where fields that are submitted with blank values aren't added to req.body and one of my pieces of code was expecting them to be there.

For instance if I had the following input field:

<input type="text" id="name" name="conversation[name]" />

And this was submitted with a blank value I would still expect the req.body to be:

console.log(req.body)
// { conversation: { name: '' } }

But I actually get:

console.log(req.body)
// {}

This is because of the code on line 58 of index.js returning if there is no value set.

// don't attach to the body object, if there is no value
if (!val) return;

Although it was no trouble to resolve, I was expecting those fields to be on the req.body even if they weren't filled in.

So I just wanted to know why the decision to not add blank submitted fields to req.body? Or is there a pattern that people are using that I'm not aware of?

My 'fix' was to add the following line to my module:

req.body.conversation = req.body.conversation || {};

But it seems that if I come across this again I'll have to duplicate this process again for any occurrences where this is a problem.

Would it make sense to make this an optional setting so that the user can decide if they want to add them to req.body or not?

Something along the lines of:

if (options.stripBlank && !val) return;

Interested to know what you think and let me know if you want a pull request for this.

Is there a way to access the file path and original file name in the rename function?

I try to rename an incoming file chunk accessing the filename parameter, but the filename is set to "blob"!! I think i misunderstand the hole concept of file uploading.... in my mind the process is something like this: the file is sent from client to server one chunk at a time that is stored in a temporary folder and after completion i must resemble this temporary chunks into the sent file and move it to a permanent folder! I was using Flow.js to allow a "smarter" upload process where the client check what chunks was already uploaded and start from there in case of some previous failure, but i'm having trouble to integrate multer with Flow.js to have this nice functionality on! Anyone could help my stupidity in this matter? :)

async rename

Hello,

I noticed the rename function uses a return value. Can this be done inside a callback? or would it simply return undefined? I need to fetch an ID for the image which would be a database call like so:

rename: function (fieldname, filename) {
  getNextPhotoId(function(id){
    return id + ".jpg";
  }
}

is this possible with multer?

Non changing file problem

I have been searching for a replacement for connect.multipart and found multer. Thank you for this.

I have been testing it in my project and I have found this, if you submit a form without having filled every file field, you get an error in index.js:52 because of the absence of filename so split throws an exception.

It can be avoided assigning an empty value if undefinned. I'm new to forks and pull request in Github but I'm trying to do a pull request.

Stop/Prevent file upload if user not authorized

I'm looking for a way to prevent upload in case of not authenticated user

I'm using Express which is configured to use passport as auth middelware.

I thought to use onFileUploadStart to reject the file, but I cannot find a link with "request" object, with which it would be possible to match the user.

Thanks
Lorenzo

support multiple files

I have this in my form:

<input accept="image/svg+xml" name="file" id="file" type="file" multiple>

It correctly lets me select multiple SVG files, and I am doing client-side HTML5 stuff, and I can read multiple files. I'd prefer to not have to base64-encode them, client-side. The req.files I get back looks like this:

{ "file": 
   { "fieldname": "file",
     "originalname": "6.svg",
     "name": "ce21d25aee1282a3fe654c10976434b1.svg",
     "encoding": "7bit",
     "mimetype": "image/svg+xml",
     "path": "uploads/ce21d25aee1282a3fe654c10976434b1.svg",
     "extension": "svg" } }

file should be an array.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.