middleware multer
Multer è un middleware node.js per gestire multipart/form-data, che viene utilizzato principalmente per caricare file. È scritto
in cima a busboy per la massima efficienza.
NOTA: Multer non elaborerà alcun modulo che non sia multipart (multipart/form-data).
Installazione
npm install multeryarn add multerpnpm add multerbun add multerNote
multer does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from DefinitelyTyped as a development dependency:
npm install --save-dev @types/multeryarn add --dev @types/multerpnpm add --save-dev @types/multerbun add --dev @types/multerUtilizzo
Multer aggiunge un oggetto body e un oggetto file o files all’oggetto request. L’oggetto body contiene i valori dei campi di testo del modulo, l’oggetto file o files contiene i file caricati attraverso il modulo.
Esempio di utilizzo di base:
Non dimenticare il enctype="multipart/form-data" nel tuo modulo.
<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 uploadMiddleware = upload.fields([ { name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 },]);app.post('/cool-profile', uploadMiddleware, 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});Nel caso in cui tu abbia bisogno di gestire un modulo multipart solo testo, dovresti usare il metodo .none():
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});Ecco un esempio su come multer viene utilizzato in un formato HTML. Prendi nota dei campi enctype="multipart/form-data" e name="uploaded_file":
<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>Poi nel file javascript si aggiungerebbero queste righe per accedere sia al file che al corpo. È importante utilizzare il valore del campo name dal modulo nella funzione di upload. Questo dice più campo sulla richiesta in cui dovrebbe cercare i file. Se questi campi non sono gli stessi nel modulo HTML e sul tuo server, il caricamento fallirà:
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);});Complete client-side and server-side examples (browser FormData uploads of a
blob and of an image) are in the examples/ folder.
API
Informazioni sul file
Ogni file contiene le seguenti informazioni:
| Chiave | Descrizione | Nota |
|---|---|---|
fieldname | Nome del campo specificato nella forma | |
originalname | Name of the file on the user’s computer, or the full path when preservePath: true | |
encoding | Tipo di codifica del file | |
mimetype | Tipo MIME del file | |
size | Dimensione del file in byte | |
destinazione | La cartella in cui il file è stato salvato | DiskStorage |
nomefile | Il nome del file all’interno della destinazione | DiskStorage |
path | Il percorso completo del file caricato | DiskStorage |
buffer | Un Buffer dell’intero file | MemoryStorage |
multer(opts)
Multer accetta un oggetto opzioni, il più basilare di cui è la proprietà dest
, che dice a Multer dove caricare i file. Nel caso in cui si ometta l’oggetto opzioni
, i file saranno conservati in memoria e mai scritti su disco.
Per impostazione predefinita, Multer rinominerà i file in modo da evitare conflitti di nomi. La funzione di rinominazione può essere personalizzata in base alle tue esigenze.
Di seguito sono riportate le opzioni che possono essere passate a Multer.
| Chiave | Descrizione |
|---|---|
defCharset | Default character set to use for text field values that do not declare one. Default: 'utf8' |
defParamCharset | Set di caratteri predefinito da usare per i valori dei parametri dell’intestazione della parte (ad esempio nome file) che non sono parametri estesi (che contengono un set di caratteri esplicito). Predefinito: 'latin1' |
dest o storage | Dove memorizzare i file |
fileFilter | Funzione per controllare quali file sono accettati |
fileHwm | highWaterMark of each file stream (file.stream). Default: busboy’s default |
highWaterMark | highWaterMark of the multipart parser stream. Default: busboy’s default |
limits | Limiti dei dati caricati |
preservePath | Keep the full client-supplied path in file.originalname instead of just the base name |
streamHandler | Function that feeds the request body to busboy; defaults to req.pipe(busboy) |
In una media web app, potrebbe essere richiesto solo dest, e configurato come mostrato in
il seguente esempio.
const upload = multer({ dest: 'uploads/' });When preservePath is enabled, Multer passes the incoming filename through with
any path segments provided by the client. This is exposed as file.originalname;
it does not change the destination folder, create directories, or sanitize the
path for you. file.originalname is always client-supplied and should be treated
as untrusted; with preservePath it additionally contains the path segments the
client sent. Normalize or validate it before using it in a custom filename or
storage engine.
Se vuoi più controllo sui tuoi upload, vuoi usare l’opzione storage
invece di dest. Navi multiple con motori di stoccaggio DiskStorage
e MemoryStorage; Più motori sono disponibili da terze parti.
.single(fieldname)
Accetta un singolo file con il nome fieldname. Il singolo file sarà archiviato
in req.file.
.array(fieldname[, maxCount])
Accetta un array di file, tutti con il nome fieldname. Opzionalmente errore se
più di file maxCount vengono caricati. L’array dei file sarà memorizzato in
req.files.
Files skipped by fileFilter do not count towards maxCount. Use
limits.files to bound how many files are read from a request.
.fields(fields)
Accetta un mix di file, specificato da fields. Un oggetto con array di file
verrà memorizzato in req.files.
fields dovrebbe essere un array di oggetti con name ed eventualmente un maxCount.
Esempio:
[ { name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 },];.none()
Accetta solo campi di testo. If any file upload is made, error with code
LIMIT_UNEXPECTED_FILE will be issued.
.any()
Accepts all files that come over the wire. Un array di file sarà memorizzato in
req.files.
ATTENZIONE: Assicurati di gestire sempre i file caricati da un utente. Non aggiungere mai multer come middleware globale poiché un utente dannoso potrebbe caricare i file su un percorso che non ti aspettavi. Usa questa funzione solo sugli itinerari dove gestisci i file caricati.
storage
DiskStorage
Il motore di archiviazione del disco ti dà pieno controllo sulla memorizzazione dei file su disco.
const crypto = require('crypto');
const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, '/tmp/my-uploads'); }, filename: function (req, file, cb) { crypto.randomBytes(16, function (err, raw) { if (err) return cb(err); cb(null, file.fieldname + '-' + raw.toString('hex')); }); },});
const upload = multer({ storage: storage });There are three options available: destination, filename and flush. All of
them except flush are functions that determine where the file should be
stored.
destination è usato per determinare in quale cartella i file caricati dovrebbero
essere memorizzati. Questo può anche essere dato come una string (ad esempio '/tmp/uploads'). If no
destination is given, the operating system’s default directory for temporary
files is used.
Nota: Sei responsabile della creazione della directory quando fornisci come funzione destinazione
. Quando si passa una stringa, multer si assicurerà che
la directory viene creata per te.
filename è usato per determinare cosa il file dovrebbe essere nominato all’interno della cartella.
Se non viene fornito alcun nome file, ad ogni file verrà dato un nome casuale che non
include alcuna estensione del file.
Nota: Multer non aggiungerà alcuna estensione del file per te, la tua funzione dovrebbe restituire un nome file completo di estensione del file.
Ogni funzione viene superata sia la richiesta (req) che alcune informazioni su
il file (file) per aiutare con la decisione.
Nota che req.body potrebbe non essere stato ancora completamente popolato. Dipende dall’ordine
che il client trasmette campi e file al server.
Per capire la convenzione di chiamata utilizzata nel callback (necessità di passare null come primo parametro), fare riferimento a Node. s gestione degli errori
flush is an optional boolean. When set to true, the file data is flushed to
disk with an fsync call before the upload handler runs, which prevents data
loss if the process or the system crashes while the data is still sitting in
the operating system’s page cache. It is disabled by default because forcing a
disk flush on every upload has a performance cost. Note that this syncs the
file contents only; if the new directory entry must survive a crash as well,
fsync the destination directory yourself.
MemoryStorage
Il motore di memorizzazione memoria memorizza i file in memoria come oggetti Buffer. non ha alcuna opzione.
const storage = multer.memoryStorage();const upload = multer({ storage: storage });Quando si utilizza memoria di memoria, le informazioni del file conterranno un campo chiamato
buffer che contiene l’intero file.
ATTENZIONE: Caricare file molto grandi o file relativamente piccoli in grandi numeri molto rapidamente, può causare che l’applicazione esaurisca la memoria quando viene utilizzata la memoria .
limits
Un oggetto che specifica i limiti di dimensione delle seguenti proprietà opzionali. Multer passes this object into busboy directly, and the details of the properties can be found on busboy’s page.
limits can also be a function that receives the request and returns such an
object. It is called once per request, before parsing starts, so limits can
depend on e.g. the authenticated user:
const upload = multer({ limits: function (req) { return { fileSize: req.user.maxUploadSize }; },});Limits apply to the whole request; there is no per-file limit. To restrict
individual files by type or name, use fileFilter or a custom storage engine.
Sono disponibili i seguenti valori interi:
| Chiave | Descrizione | Predefinito |
|---|---|---|
fieldNameSize | Dimensione massima nome campo | Infinito |
fieldSize | Dimensione massima del campo (in byte) | 1MB |
fields | Numero massimo di campi non file | Infinito |
fileSize | Per forme multiple, la dimensione massima del file (in byte) | Infinito |
files | Per forme multiple, il numero massimo di campi di file | Infinito |
parts | Per forme multiple, il numero massimo di parti (campi + file) | Infinito |
headerPairs | Per forme multiparti, il numero massimo di chiavi intestazione=>valore coppie da analizzare | 2000 |
fieldNestingDepth | Max number of nesting levels for field names (e.g. a[b][c] has 2 levels) | Infinito |
fieldArrayIndexLimit | Max numeric array index accepted inside a field name (e.g. a[3] uses index 3) | Infinito |
Specificare i limiti può aiutare a proteggere il vostro sito dagli attacchi di negazione del servizio (DoS).
fileFilter
Impostare questa funzione per controllare quali file devono essere caricati e quali devono essere saltati. La funzione dovrebbe apparire così:
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!"));}streamHandler
By default Multer reads the request with req.pipe(busboy). Some platforms
consume the request body before your handlers run, so there is nothing left to
pipe. Google Cloud Functions and Firebase Functions, for example, expose the
already-read body as req.rawBody. Provide a streamHandler to feed busboy
yourself in that case:
const upload = multer({ storage: multer.memoryStorage(), streamHandler: function (req, busboy) { if (req.rawBody) { busboy.end(req.rawBody); } else { req.pipe(busboy); } },});The function receives the request and the busboy instance and must write the whole multipart body to busboy and end it.
Security
Specifying the limits can help protect your site against denial of service (DoS) attacks. The following limits are recommended for most applications:
fileSize— set to the maximum expected file size for your use casefiles— set to the maximum number of files per requestfields— set to the maximum number of text fields per requestfieldNestingDepth— set to the minimum depth your field names require (e.g.3fora[b][c])fieldArrayIndexLimit— set to the largest array index your field names require (e.g.100fora[99])
Gestione errori
Quando si incontra un errore, Multer delegherà l’errore a Express. Puoi visualizzare una bella pagina di errore usando lo standard express way.
Se si desidera catturare errori specificamente da Multer, è possibile chiamare la funzione middleware
da soli. Inoltre, se si desidera catturare solo gli errori Multer, puoi usare la classe MulterError che è collegata all’oggetto multer stesso (e. . err instanceof multer.MulterError).
Multer errors carry a code (e.g. LIMIT_FILE_SIZE) and, when the error concerns
a specific field, its name in field. Errors about a specific file
(LIMIT_FILE_SIZE, LIMIT_UNEXPECTED_FILE) also expose the client-supplied file
name in filename; treat it as untrusted input, like file.originalname.
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. });});Motore di stoccaggio personalizzato
Per informazioni su come costruire il proprio motore di archiviazione, vedere Multer Storage Engine.