function multer(options) { if (options === undefined) { return new Multer({}) } if (typeof options === 'object' && options !== null) { return new Multer(options) } throw new TypeError('Expected object for argument options') }
n/a
function Counter() { EventEmitter.call(this) this.value = 0 }
n/a
diskStorage = function (opts) { return new DiskStorage(opts) }
...
### `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())
}
})
...
function FileAppender(strategy, req) { this.strategy = strategy this.req = req switch (strategy) { case 'NONE': break case 'VALUE': break case 'ARRAY': req.files = []; break case 'OBJECT': req.files = Object.create(null); break default: throw new Error('Unknown file strategy: ' + strategy) } }
n/a
memoryStorage = function (opts) { return new MemoryStorage(opts) }
...
#### `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
...
function Counter() { EventEmitter.call(this) this.value = 0 }
n/a
function decrement() { if (--this.value === 0) this.emit('zero') }
...
Object.defineProperty(file, 'stream', {
configurable: true,
enumerable: false,
value: fileStream
})
fileStream.on('error', function (err) {
pendingWrites.decrement()
abortWithError(err)
})
fileStream.on('limit', function () {
aborting = true
abortWithCode('LIMIT_FILE_SIZE', fieldname)
})
...
function increment() { this.value++ }
...
if (!includeFile) {
appender.removePlaceholder(placeholder)
return fileStream.resume()
}
var aborting = false
pendingWrites.increment()
Object.defineProperty(file, 'stream', {
configurable: true,
enumerable: false,
value: fileStream
})
...
function isZero() { return (this.value === 0) }
...
}
Counter.prototype.isZero = function isZero () {
return (this.value === 0)
}
Counter.prototype.onceZero = function onceZero (fn) {
if (this.isZero()) return fn()
this.once('zero', fn)
}
module.exports = Counter
...
function onceZero(fn) { if (this.isZero()) return fn() this.once('zero', fn) }
...
if (readFinished && pendingWrites.isZero() && !errorOccured) done()
}
function abortWithError (uploadError) {
if (errorOccured) return
errorOccured = true
pendingWrites.onceZero(function () {
function remove (file, cb) {
storage._removeFile(req, file, cb)
}
removeUploadedFiles(uploadedFiles, remove, function (err, storageErrors) {
if (err) return done(err)
...
function FileAppender(strategy, req) { this.strategy = strategy this.req = req switch (strategy) { case 'NONE': break case 'VALUE': break case 'ARRAY': req.files = []; break case 'OBJECT': req.files = Object.create(null); break default: throw new Error('Unknown file strategy: ' + strategy) } }
n/a
insertPlaceholder = function (file) { var placeholder = { fieldname: file.fieldname } switch (this.strategy) { case 'NONE': break case 'VALUE': break case 'ARRAY': this.req.files.push(placeholder); break case 'OBJECT': if (this.req.files[file.fieldname]) { this.req.files[file.fieldname].push(placeholder) } else { this.req.files[file.fieldname] = [placeholder] } break } return placeholder }
...
var file = {
fieldname: fieldname,
originalname: filename,
encoding: encoding,
mimetype: mimetype
}
var placeholder = appender.insertPlaceholder(file)
fileFilter(req, file, function (err, includeFile) {
if (err) {
appender.removePlaceholder(placeholder)
return abortWithError(err)
}
...
removePlaceholder = function (placeholder) { switch (this.strategy) { case 'NONE': break case 'VALUE': break case 'ARRAY': arrayRemove(this.req.files, placeholder); break case 'OBJECT': if (this.req.files[placeholder.fieldname].length === 1) { delete this.req.files[placeholder.fieldname] } else { arrayRemove(this.req.files[placeholder.fieldname], placeholder) } break } }
...
mimetype: mimetype
}
var placeholder = appender.insertPlaceholder(file)
fileFilter(req, file, function (err, includeFile) {
if (err) {
appender.removePlaceholder(placeholder)
return abortWithError(err)
}
if (!includeFile) {
appender.removePlaceholder(placeholder)
return fileStream.resume()
}
...
replacePlaceholder = function (placeholder, file) { if (this.strategy === 'VALUE') { this.req.file = file return } delete placeholder.fieldname objectAssign(placeholder, file) }
...
appender.removePlaceholder(placeholder)
pendingWrites.decrement()
return abortWithError(err)
}
var fileInfo = extend(file, info)
appender.replacePlaceholder(placeholder, fileInfo)
uploadedFiles.push(fileInfo)
pendingWrites.decrement()
indicateDone()
})
})
})
...