-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Switch to stream based API #399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 46 commits
42a9e3b
beeb22d
e5a0c4f
fff81bd
c7d1487
3719e0f
4a5c707
2bda1c3
a862274
bdb8763
b1e5ea0
fd3e47d
1923ac2
5dfa540
267bb2b
3973e33
3a94500
e7f249e
ea47167
41f39ed
f54762a
c4b223e
2b49f4f
cc381d6
ac38af4
8d5219a
14b4ba0
f3995ea
6001d34
e82146d
6c26419
a415ee5
ba6fd35
f3d9789
743b7a6
3b8fd94
db32edc
c569242
c15b6f2
f94bdc2
d762ab4
138e180
fb08b9f
ee8b4ef
639e359
f181839
b5ca4b5
ed4ce55
08d0c24
fde725d
ddc1727
ba4e105
cb526fb
b13ce1d
54061af
690f703
74456fc
15f7e80
d983eb2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,6 @@ node_modules | |
| *.log | ||
| *.gz | ||
|
|
||
|
|
||
| # Coveralls | ||
| coverage | ||
| # Code Coverage | ||
| /.nyc_output/ | ||
| /coverage/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| package-lock=false |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| sudo: false | ||
| language: node_js | ||
| node_js: | ||
| - "0.10" | ||
| - "0.12" | ||
| - "iojs-v1.8.4" | ||
| - "iojs-v2.5.0" | ||
| - "iojs-v3.3.0" | ||
| - "4" | ||
| - '13' | ||
| - '12' | ||
| - '10' | ||
| - '10.13.0' | ||
| os: | ||
| - linux | ||
| - osx | ||
| - windows |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ on top of [busboy](https://github.com/mscdex/busboy) for maximum efficiency. | |
| ## Installation | ||
|
|
||
| ```sh | ||
| $ npm install --save multer | ||
| npm install --save multer | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
@@ -18,24 +18,24 @@ Multer adds a `body` object and a `file` or `files` object to the `request` obje | |
| Basic usage example: | ||
|
|
||
| ```javascript | ||
| var express = require('express') | ||
| var multer = require('multer') | ||
| var upload = multer({ dest: 'uploads/' }) | ||
| const multer = require('multer') | ||
| const express = require('express') | ||
|
|
||
| var app = express() | ||
| const app = express() | ||
| const upload = multer() | ||
|
|
||
| app.post('/profile', upload.single('avatar'), function (req, res, next) { | ||
| app.post('/profile', upload.single('avatar'), (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) { | ||
| app.post('/photos/upload', upload.array('photos', 12), (req, res, next) => { | ||
| // req.files is array of `photos` files | ||
| // req.body will contain the text fields, if there were any | ||
| }) | ||
|
|
||
| var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) | ||
| app.post('/cool-profile', cpUpload, function (req, res, next) { | ||
| const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }]) | ||
| app.post('/cool-profile', cpUpload, (req, res, next) => { | ||
| // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files | ||
| // | ||
| // e.g. | ||
|
|
@@ -46,15 +46,16 @@ app.post('/cool-profile', cpUpload, function (req, res, next) { | |
| }) | ||
| ``` | ||
|
|
||
| In case you need to handle a text-only multipart form, you can use any of the multer methods (`.single()`, `.array()`, `fields()`). Here is an example using `.array()`: | ||
| In case you need to handle a text-only multipart form, you can use the `.none()` method, example: | ||
|
|
||
| ```javascript | ||
| var express = require('express') | ||
| var app = express() | ||
| var multer = require('multer') | ||
| var upload = multer() | ||
| const multer = require('multer') | ||
| const express = require('express') | ||
|
|
||
| app.post('/profile', upload.array(), function (req, res, next) { | ||
| const app = express() | ||
| const upload = multer() | ||
|
|
||
| app.post('/profile', upload.none(), (req, res, next) => { | ||
| // req.body contains the text fields | ||
| }) | ||
| ``` | ||
|
|
@@ -65,45 +66,27 @@ app.post('/profile', upload.array(), function (req, res, next) { | |
|
|
||
| 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 | ||
| `fieldName` | Field name specified in the form | ||
| `originalName` | Name of the file on the user's computer (`undefined` if no filename was supplied by the client) | ||
| `size` | Size of the file in bytes | ||
| `stream` | Stream of file | ||
|
LinusU marked this conversation as resolved.
Outdated
|
||
| `detectedMimeType` | The detected mime-type, or null if we failed to detect | ||
| `detectedFileExtension` | The typical file extension for files of the detected type, or empty string if we failed to detect (with leading `.` to match `path.extname`) | ||
| `clientReportedMimeType` | The mime type reported by the client using the `Content-Type` header, or null<sup>1</sup> if the header was absent | ||
| `clientReportedFileExtension` | The extension of the file uploaded (as reported by `path.extname`) | ||
|
|
||
| In an average web app, only `dest` might be required, and configured as shown in | ||
| the following example. | ||
| <sup>1</sup> Currently returns `text/plain` if header is absent, this is a bug and it will be fixed in a patch release. Do not rely on this behavior. | ||
|
|
||
| ```javascript | ||
| var upload = multer({ dest: 'uploads/' }) | ||
| ``` | ||
| ### `multer(opts)` | ||
|
|
||
| Multer accepts an options object, the following are the options that can be | ||
| passed to Multer. | ||
|
|
||
| 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. | ||
| Key | Description | ||
| -------- | ----------- | ||
| `limits` | Limits of the uploaded data [(full description)](#limits) | ||
|
|
||
| #### `.single(fieldname)` | ||
|
|
||
|
|
@@ -146,107 +129,24 @@ 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. | ||
|
|
||
| ```javascript | ||
| var storage = multer.diskStorage({ | ||
| destination: function (req, file, cb) { | ||
| cb(null, '/tmp/my-uploads') | ||
| }, | ||
| filename: function (req, file, cb) { | ||
| cb(null, file.fieldname + '-' + Date.now()) | ||
| } | ||
| }) | ||
|
|
||
| var 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. | ||
|
|
||
| #### `MemoryStorage` | ||
|
|
||
| The memory storage engine stores the files in memory as `Buffer` objects. It | ||
| doesn't have any options. | ||
|
|
||
| ```javascript | ||
| var storage = multer.memoryStorage() | ||
| var 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](https://github.com/mscdex/busboy#busboy-methods). | ||
|
|
||
| The following integer values are available: | ||
| The following limits are available: | ||
|
|
||
| Key | Description | Default | ||
| --- | --- | --- | ||
| `fieldNameSize` | Max field name size | 100 bytes | ||
| `fieldSize` | Max field value size | 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` | ||
| `fieldNameSize` | Max number of bytes per field name | `'100B'` | ||
| `fieldSize` | Max number of bytes per field value | `'8KB'` | ||
| `fields` | Max number of fields per request | `1000` | ||
| `fileSize` | Max number of bytes per file | `'8MB'` | ||
| `files` | Max number of files per request | `10` | ||
| `headerPairs` | Max number of header key-value pairs | `2000` (same as Node's http) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC, one of the outstanding issue with multer was about better observability of filtered out uploads - for example, is there any inherent mechanism / object that stores the state of failed uploads? Right now the absence of a user callback invocation means to indicate a failed upload, but absence of a callback invocation cannot be intercepted? |
||
|
|
||
| Set this to a function to control which files should be uploaded and which | ||
| should be skipped. The function should look like this: | ||
| Bytes limits can be passed either as a number, or as a string with an appropriate prefix. | ||
|
|
||
| ```javascript | ||
| 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!')) | ||
|
|
||
| } | ||
| ``` | ||
| Specifying the limits can help protect your site against denial of service (DoS) attacks. | ||
|
|
||
| ## Error handling | ||
|
|
||
|
|
@@ -257,10 +157,10 @@ If you want to catch errors specifically from multer, you can call the | |
| middleware function by yourself. | ||
|
|
||
| ```javascript | ||
| var upload = multer().single('avatar') | ||
| const upload = multer().single('avatar') | ||
|
|
||
| app.post('/profile', function (req, res) { | ||
| upload(req, res, function (err) { | ||
| app.post('/profile', (req, res) => { | ||
| upload(req, res, (err) => { | ||
| if (err) { | ||
| // An error occurred when uploading | ||
| return | ||
|
|
@@ -270,12 +170,3 @@ app.post('/profile', function (req, res) { | |
| }) | ||
| }) | ||
| ``` | ||
|
|
||
| ## Custom storage engine | ||
|
|
||
| See [the documentation here](/StorageEngine.md) if you want to build your own | ||
| storage engine. | ||
|
|
||
| ## License | ||
|
|
||
| [MIT](LICENSE) | ||
Uh oh!
There was an error while loading. Please reload this page.