57

Why is <form enctype=multipart/form-data> required when uploading a file to a web-server?

isapir
  • 21,295
  • 13
  • 115
  • 116

2 Answers2

87

It has to do with how the browser packages binary and form data for transmission over HTTP. By default only form data is sent, but if the form needs to support uploading a file, then the binary data must also be appended and separated from the form data.

Scott Hanselman gives a good explanation of this here:

HTTP and How File Upload works via HTTP

It's always better, for me, to understand WHY and HOW something is happening. If you say "just because" or "whatever, you just add that, and it works" then I think that's sad. For some reason while many folks understand FORM POSTs and generally how form data is passed up to the server, when a file is transferred many just conclude it's magic. Why do we have to add enctype="multipart/form=data" on our forms that include file uploads? Because the form will now be POSTed in multiple parts.

If you have a form like this:

<form action="/home/uploadfiles" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" value="Submit" />
</form>

The resulting Form POST will look like this (slightly simplified):

POST /home/uploadfiles HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------7d81b516112482 
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 324

-----------------------------7d81b516112482 
Content-Disposition: form-data; name="file"; filename="\\SERVER\Users\Scott\test.txt"
Content-Type: text/plain

foo
-----------------------------7d81b516112482
Content-Disposition: form-data; name="submit"

Submit
-----------------------------7d81b516112482--

Notice a few things about this POST. First, notice the content-type and boundary="" and how the boundary is used later, as exactly that, a boundary between the multiple parts. See how the first part shows that I uploaded a single file, of type text/plain. You can interpolate from this how you'd expect multiple files to show up if they were all POSTed at once.

And of course, look at how different this would look if it were just a basic form POST without the enctype="multipart/form=data" included:

POST /home/uploadfiles HTTP/1.1 
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 13

submit=Submit

See how the content type is different? This is a regular, typical form POST. Perhaps atypical in that it includes only a Submit button! ....

As an aside, if you looked at an email of yours with multiple attached files, it would look VERY similar to the body of the first HTTP message as multipart MIME encoding is found everywhere, as is common with most good ideas.

Community
  • 1
  • 1
Nathan Taylor
  • 24,423
  • 19
  • 99
  • 156
  • can you please explain what is binary data when uploading text file ? Say i uploading text file , why it is can be sent as request parameter in post body where parameter name can be file name and value can be file content ? Basically If I can manually paste the file content in text area on HTML/JSP which is transferred to server as normal post request parameter that read it on server side then why file upload requires multi part form ? – scott miles Aug 06 '17 at 14:20
  • How multipart will work if the webserver is behind a loadbalancer ? – Knight71 Oct 19 '20 at 13:15
  • @scottmiles Far overdue, but the answer to your question pertains to the type of data. Plain text data may be transferred as such with no loss of fidelity, given the proper encoding, but non-text data (videos, images, etc) is more complex and not intended to be encoded as plain text. – Nathan Taylor Feb 17 '21 at 19:42
  • 1
    @Knight71 multipart refers to the format of the payload, not the request itself. It is still transferred as one continuous stream by the client to a server with some pre-determined address (IP), and the multi-part boundaries are used so that the server can reassemble the different parts of the payload correctly (for example form data, and two separate files). – Nathan Taylor Feb 17 '21 at 19:44
  • @NathanTaylor so if I want to send big file to server by chunks multipart won't help me with this right? – Akmal Salikhov Nov 07 '21 at 11:38
5

That is part of the specification for HTML File Upload as described in RFC-1867, which was the proposal to allow file uploads in HTML forms (circa 1995).

From section 2:

This proposal makes two changes to HTML:

1) Add a FILE option for the TYPE attribute of INPUT.
2) Allow an ACCEPT attribute for INPUT tag, which is a list of media types or type patterns allowed for the input.

In addition, it defines a new MIME media type, multipart/form-data, and specifies the behavior of HTML user agents when interpreting a
form with ENCTYPE="multipart/form-data" and/or <INPUT type="file">
tags.

When you set enctype to multipart/form-data, the browser separates each file or attachment in the upload with a "multipart boundary", which is a unique identifier that defines the beginning and end of each "part".

That allows the browser to send multiple parts (hence the name) in one request, and identify each one with its own metadata like mime type, file name, etc.

isapir
  • 21,295
  • 13
  • 115
  • 116