Cosa significa enctype = 'multipart / form-data'?


Risposte:


1570

Quando si effettua una richiesta POST, è necessario codificare i dati che formano il corpo della richiesta in qualche modo.

I moduli HTML forniscono tre metodi di codifica.

  • application/x-www-form-urlencoded (il predefinito)
  • multipart/form-data
  • text/plain

Si stava lavorando per aggiungere application/json, ma questo è stato abbandonato.

(Altre codifiche sono possibili con richieste HTTP generate utilizzando mezzi diversi dall'invio di un modulo HTML. JSON è un formato comune da utilizzare con i servizi Web e alcuni usano ancora SOAP.)

Le specifiche dei formati non contano per la maggior parte degli sviluppatori. I punti importanti sono:

  • Non utilizzare mai text/plain.

Quando si scrive un codice lato client:

  • utilizzare multipart/form-dataquando il modulo include <input type="file">elementi
  • altrimenti puoi usare multipart/form-datao application/x-www-form-urlencodedma application/x-www-form-urlencodedsarai più efficiente

Quando si scrive un codice lato server:

  • Utilizzare una libreria di gestione moduli pre-scritta

La maggior parte (come quella di Perl CGI->paramo quella esposta dal $_POSTsuperglobal di PHP ) si prenderà cura delle differenze per te. Non preoccuparti di provare a analizzare l'input non elaborato ricevuto dal server.

A volte troverai una libreria che non è in grado di gestire entrambi i formati. La libreria più popolare di Node.js per la gestione dei dati dei moduli è body-parser che non è in grado di gestire richieste multipart (ma ha una documentazione che consiglia alcune alternative che possono).


Se stai scrivendo (o eseguendo il debug) di una libreria per l'analisi o la generazione di dati non elaborati, devi iniziare a preoccuparti del formato. Potresti anche volerlo sapere per interesse.

application/x-www-form-urlencoded è più o meno uguale a una stringa di query alla fine dell'URL.

multipart/form-dataè significativamente più complicato ma consente di includere interi file nei dati. Un esempio del risultato può essere trovato nella specifica HTML 4 .

text/plainè introdotto da HTML 5 ed è utile solo per il debug - dalle specifiche : non sono interpretabili in modo affidabile dal computer - e direi che gli altri combinati con strumenti (come il Pannello di rete negli strumenti di sviluppo della maggior parte dei browser) sono migliori per quello).


5
@Quentin Mi scusi, quale sarà un probabile problema se utilizziamo multipart per tutti i moduli? con e con i file.
Webinan,

12
Non ha senso per i moduli GET e aumenta le dimensioni del file delle richieste.
Quentin,

@Quentin i dati dei moduli multipart vengono inviati come flusso per impostazione predefinita?
Growler,

Enc in enctype rappresenta qualcosa?
Philip Rego,

1
"I moduli HTML forniscono tre metodi di oding ENC "
Quentin,

449

quando dovremmo usarlo

La risposta di Quentin è corretta: utilizzare multipart/form-datase il modulo contiene un caricamento di file e application/x-www-form-urlencoded, in caso contrario, è l'impostazione predefinita se si omette enctype.

Sto andando a:

  • aggiungere altri riferimenti HTML5
  • spiega perché ha ragione con un modulo invia un esempio

Riferimenti HTML5

Esistono tre possibilità per enctype:

Come generare gli esempi

Una volta che vedi un esempio di ciascun metodo, diventa ovvio come funzionano e quando dovresti usarli.

Puoi produrre esempi usando:

Salvare il modulo in un .htmlfile minimo :

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8"/>
  <title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
  <p><input type="text" name="text1" value="text default">
  <p><input type="text" name="text2" value="a&#x03C9;b">
  <p><input type="file" name="file1">
  <p><input type="file" name="file2">
  <p><input type="file" name="file3">
  <p><button type="submit">Submit</button>
</form>
</body>
</html>

Impostiamo il valore di testo predefinito su a&#x03C9;b, il che significa aωbperché ωè U+03C9, che sono i byte 61 CF 89 62in UTF-8.

Crea file da caricare:

echo 'Content of a.txt.' > a.txt

echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html

# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary

Esegui il nostro piccolo server echo:

while true; do printf '' | nc -l 8000 localhost; done

Apri l'HTML sul tuo browser, seleziona i file e fai clic su Invia e controlla il terminale.

nc stampa la richiesta ricevuta.

Testato su: Ubuntu 14.04.3, ncBSD 1.105, Firefox 40.

multipart / form-data

Firefox inviato:

POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834

-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"

text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"

aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain

Content of a.txt.

-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html

<!DOCTYPE html><title>Content of a.html.</title>

-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream

aωb
-----------------------------735323031399963166993862150--

Per il file binario e il campo di testo, i byte 61 CF 89 62( aωbin UTF-8) vengono inviati letteralmente. Puoi verificarlo con nc -l localhost 8000 | hd, che dice che i byte:

61 CF 89 62

sono stati inviati ( 61== 'a' e 62== 'b').

Pertanto è chiaro che:

  • Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150imposta il tipo di contenuto su multipart/form-datae dice che i campi sono separati dalla boundarystringa data .

    Ma nota che:

    boundary=---------------------------735323031399963166993862150

    ha due paphes in meno --rispetto alla barriera reale

    -----------------------------735323031399963166993862150

    Questo perché lo standard richiede che il limite inizi con due trattini --. Gli altri trattini sembrano essere proprio come Firefox ha scelto di implementare il confine arbitrario. RFC 7578 menziona chiaramente che --sono necessari quei due trattini principali :

    4.1. Parametro "Boundary" di multipart / form-data

    Come con altri tipi multipart, le parti sono delimitate da un delimitatore di limite, costruito usando CRLF, "-" e il valore del parametro "limite".

  • ogni campo ottiene alcuni sottotitoli prima dei suoi dati:, Content-Disposition: form-data;il campo name, il filename, seguito dai dati.

    Il server legge i dati fino alla stringa di limite successiva. Il browser deve scegliere un limite che non verrà visualizzato in nessuno dei campi, quindi è per questo che il limite può variare tra le richieste.

    Poiché abbiamo il limite univoco, non è necessaria alcuna codifica dei dati: i dati binari vengono inviati così come sono.

    TODO: qual è la dimensione del limite ottimale ( log(N)scommetto) e il nome / tempo di esecuzione dell'algoritmo che lo trova? Chiesto a: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences

  • Content-Type viene determinato automaticamente dal browser.

    Come viene determinato esattamente è stato chiesto a: Come viene determinato il tipo mime di un file caricato dal browser?

application / x-www-form-urlencoded

Ora modifica il enctypein application/x-www-form-urlencoded, ricarica il browser e reinvia.

Firefox inviato:

POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51

text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary

Chiaramente i dati del file non sono stati inviati, solo i nomi di base. Quindi questo non può essere usato per i file.

Per quanto riguarda il campo di testo, vediamo che al solito i caratteri stampabili come ae bsono stati inviati in un byte, mentre quelli non stampabili come 0xCFe 0x89presero 3 byte ciascuno: %CF%89!

Confronto

I caricamenti di file contengono spesso molti caratteri non stampabili (ad esempio immagini), mentre i moduli di testo non lo fanno quasi mai.

Dagli esempi abbiamo visto che:

  • multipart/form-data: aggiunge alcuni byte di sovraccarico al confine al messaggio e deve impiegare del tempo per calcolarlo, ma invia ogni byte in un byte.

  • application/x-www-form-urlencoded: ha un limite di byte singolo per campo ( &), ma aggiunge un fattore di sovraccarico lineare di 3x per ogni carattere non stampabile.

Pertanto, anche se potessimo inviare file con application/x-www-form-urlencoded, non vorremmo, perché è così inefficiente.

Ma per i caratteri stampabili che si trovano nei campi di testo, non importa e genera meno sovraccarico, quindi lo usiamo e basta.


3
@ Khanna111 %CFè 3 byte lunghi: %, Ce F:-) Storia di renderlo leggibile.
Ciro Santilli 6 冠状 病 六四 事件 法轮功

6
Su OS X, ncnon accetteranno contemporaneamente sia -ll' -pargomento che l' argomento. Ma questo funziona per me: while true; do printf '' | nc -l 8000; done.
Filippo

4
Un piccolo ma importante punto che non è menzionato è che il limite specificato in Content-Typeha due trattini ( --) in meno, cioè quando si utilizza effettivamente il limite nel corpo del messaggio, è necessario prefissarlo --. Inoltre, è necessario aggiungere l'ultimo limite --, ma è abbastanza facile da notare. Vedi stackoverflow.com/questions/3508252/…
Bernard

1
Per quanto ne so, il punto di mettere TUTTI I DISEGNI AL limite è rendere impossibile controllare a occhio la sintassi della richiesta. Per favore, non usarli nei token di confine.
Dewi Morgan,

1
@DewiMorgan Hai perfettamente ragione. Ho modificato il post e rimosso i trattini dalla stringa di confine.
Max

91

enctype='multipart/form-dataè un tipo di codifica che consente l'invio di file tramite un POST . Molto semplicemente, senza questa codifica i file non possono essere inviati tramite POST .

Se si desidera consentire a un utente di caricare un file tramite un modulo, è necessario utilizzare questo tipo di codifica .


Quindi .. se il file non è un file binario, allora possiamo lavorare senza questo?
Yugal Jindle,

Da quello che ho capito, puoi usare multipart/form-dataper inviare file non binari ma è inefficiente. Credo che l'utilizzo application/x-www-form-urlencodedsia il modo corretto per inviare dati non binari, ma qualcuno con più esperienza con i file non binari potrebbe aver bisogno di correggermi.
Matt Asbury,

11
Il vantaggio principale dell'utilizzo multipart/form-dataper l'invio di un file è che funzionerà automaticamente sia in frontend che in backend. Non è necessario eseguire alcuna gestione speciale. Tutti i file sono binari anche se devono contenere solo testo. application/x-www-form-urlencodedè il modo standard per inviare un modulo senza file allegati. multipart/form-dataè il modo standard per inviare un modulo con file allegati. (Esistono anche numerose altre codifiche, come application/jsoneapplication/json-patch+json , che sono comuni per la comunicazione tra server e client.)
Daniel Luna,

6
Vale la pena sottolineare che base64 può codificare l'immagine e inviarla come semplici dati stringa.
James,

3
Oltre al commento di @ Prospero sopra: puoi assolutamente inviare file tramite POST senza usare multipart/form-data. Quello che non puoi fare è farlo usando un normale invio di moduli HTML, senza JavaScript. L'impostazione di un modulo da utilizzare multipart/form-dataè l'unico meccanismo fornito da HTML per consentire ai file POST di utilizzare JavaScript. Sento che questo non è abbastanza chiaro nella risposta e che un lettore ingenuo potrebbe pensare che l'incapacità di inviare file senza multipart/form-datasia una limitazione di HTTP ; non è così.
Mark Amery

81

Quando si invia un modulo, si comunica al proprio browser di inviare, tramite il protocollo HTTP, un messaggio sulla rete, correttamente avvolto in una struttura di messaggi del protocollo TCP / IP. Una pagina HTML ha un modo per inviare dati al server: usando <form>s.

Quando viene inviato un modulo, viene creata e inviata una richiesta HTTP al server, il messaggio conterrà i nomi dei campi nel modulo e i valori compilati dall'utente. Questa trasmissione può avvenire con metodi HTTPPOST o .GET

  • POST dice al tuo browser di creare un messaggio HTTP e di inserire tutto il contenuto nel corpo del messaggio (un modo molto utile di fare le cose, più sicuro e anche flessibile).
  • GETinvierà i dati del modulo nella stringa di query . Ha alcuni vincoli sulla rappresentazione e la lunghezza dei dati.

Indicare come inviare il modulo al server

L'attributo enctypeha senso solo quando si usaPOST metodo. Se specificato, indica al browser di inviare il modulo codificandone il contenuto in un modo specifico. Da MDN - Tipo di modulo :

Quando il valore dell'attributo del metodo è post, enctype è il tipo di contenuto MIME utilizzato per inviare il modulo al server.

  • application/x-www-form-urlencoded: Questo è il valore predefinito. Quando il modulo viene inviato, vengono raccolti tutti i nomi e i valori e la codifica URL viene eseguita sulla stringa finale.
  • multipart/form-data: I caratteri NON sono codificati. Ciò è importante quando il modulo ha un controllo di caricamento dei file. Si desidera inviare il file binario e questo garantisce che il flusso di bit non venga modificato.
  • text/plain: Gli spazi vengono convertiti, ma non viene più eseguita la codifica.

Sicurezza

Quando si inviano i moduli, possono sorgere alcuni problemi di sicurezza come indicato nella Sezione 7 di RFC 7578: Dati dei moduli multipart - Considerazioni sulla sicurezza :

Tutti i software di elaborazione dei moduli devono trattare i dati dei moduli forniti dagli utenti
con sensibilità, poiché spesso contengono informazioni riservate o di
identificazione personale . Vi è un uso diffuso delle funzioni di "riempimento automatico" dei moduli nei browser Web; questi potrebbero essere utilizzati per indurre gli utenti a
inviare inconsapevolmente informazioni riservate durante il completamento di attività altrimenti
innocue. i dati multipart / form non forniscono alcuna funzionalità
per controllare l'integrità, garantire la riservatezza, evitare la
confusione dell'utente o altre funzionalità di sicurezza; tali preoccupazioni devono essere
affrontate dalle domande di compilazione e interpretazione dei moduli.

Le domande che ricevono i moduli e li elaborano devono fare attenzione a non restituire dati al sito di elaborazione dei moduli richiedente che non era destinato a essere inviato.

È importante quando si interpreta il nome del file dell'intestazione Content-
Disposition per non sovrascrivere inavvertitamente i file nello
spazio file del destinatario.

Ciò ti preoccupa se sei uno sviluppatore e il tuo server elaborerà i moduli inviati dagli utenti che potrebbero finire per contenere informazioni riservate.


1
Le cose sulla sicurezza dopo l'ultima modifica sono tutte irrilevanti per la domanda su cosa enctypefacciano. So che proviene letteralmente multipart/form-datadall'RFC, ma è comunque un dump arbitrario di considerazioni sulla sicurezza relative all'invio di moduli che sono completamente ortogonali al fatto che i dati vengano inviati come application/x-www-form-urlencodedo multipart/form-data.
Mark Amery,

38

enctype='multipart/form-data'significa che nessun carattere verrà codificato. ecco perché questo tipo viene utilizzato durante il caricamento di file sul server. Viene
quindi multipart/form-datautilizzato quando un modulo richiede il caricamento di dati binari, come il contenuto di un file


8

Impostare l'attributo del metodo su POST perché il contenuto del file non può essere inserito in un parametro URL utilizzando un modulo.

Impostare il valore di enctype su multipart / form-data poiché i dati verranno suddivisi in più parti, una per ogni file più una per il testo del corpo del modulo che può essere inviato con loro.


Ciò implica che POSTè probabilmente sufficiente per inviare un file tramite un modulo e che l'aggiunta multipart/form-dataè solo un bonus in qualche modo vago. Non è così. La maggior parte dei file richiederà assolutamente l'utilizzo multipart/form-data.
underscore_d

1
  • L'attributo enctype ( ENC ode TYPE ) specifica come i dati del modulo devono essere codificati durante l'invio al server.
  • multipart / form-data è uno dei valori dell'attributo enctype, che viene utilizzato nell'elemento form che ha un caricamento di file. multiparte significa che i dati del modulo vengono suddivisi in più parti e inviati al server.

5
Credo che enctype non rappresenti il ​​tipo di crittografia. Non esiste alcuna crittografia a questo livello. La mia ipotesi è il tipo di codifica o il tipo racchiuso. Ma sicuramente non è un tipo di crittografia.
Yeo

1
Il tuo punto di proiettile finale qui circa <head>ed <body>è irrilevante e confusione.
Mark Amery,

0

Di solito questo è quando hai un modulo POST che deve prendere un caricamento di file come dati ... questo dirà al server come codificherà i dati trasferiti, in tal caso non verrà codificato perché trasferirà e caricherà i file sul server, come ad esempio quando si carica un'immagine o un pdf


-3

L'attributo enctype specifica come codificare i dati del modulo quando lo si inoltra al server.

L'attributo enctype può essere utilizzato solo se method = "post".

Nessun carattere è codificato. Questo valore è richiesto quando si utilizzano moduli che dispongono di un controllo di caricamento dei file

Da W3Schools


2
Questa citazione non menziona nemmeno multipart/form-data. È anche abbastanza poco chiaro; cosa significa la frase "Nessun carattere codificato"? -1.
Mark Amery,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.