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()
})
})
})
...