Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it okay to use enctype="multipart/form-data" on a form that does not have a file input

Tags:

html

php

On my server (which runs PHP 5.4), I have a generalized way of delivering forms from database-connected objects. Some of the objects will have a file input, and some of them will not. I would prefer to just always set enctype="multipart/form-data" rather than scrape the form (or database object) to see if it contains an <input type="file" /> and do it conditionally.

I tested it with a form like <form enctype="multipart/form-data" action="blah" method="post"><input type="text" name="name" /></form> and the data was received exactly the same (from the $_POST param) as when I leave enctype blank.

So, my test says it's okay, but is there any reason why I would should leave off the enctype="multipart/form-data" for form submissions that don't contain a file?

like image 730
Reed Avatar asked Jan 07 '23 23:01

Reed


2 Answers

Short answer: yes.

Slightly longer answer: yes, but you'll increase the size of POST payloads (and thereby increase the amount of time required to submit the form) ever so slightly.

Let's look at what actually gets sent to the browser for a POST request. I used nc(1) to listen on a port, and then used Firefox to blast it with a request from a simple HTML page with two form fields: foo, the value of which was a, and bar, the value of which was b.

Without specifying an enctype, the browser will default to application/x-www-form-urlencoded. This is what was sent:

POST / HTTP/1.1
Host: localhost:9000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.1.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-CA,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://localhost/form.html
Cookie: style=null; org.cups.sid=26d9134b774e3f9237c14f9f3fbe9082
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

foo=a&bar=b

Fields are sent as URL-encoded key/value pairs, just like in a GET request. The only difference is that you can send more data. Simple as pie.

The multipart/form-data submission, on the other hand, is considerably bulkier:

POST / HTTP/1.1
Host: localhost:9000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.1.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-CA,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://localhost/form.html
Cookie: style=null; org.cups.sid=26d9134b774e3f9237c14f9f3fbe9082
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------1894318417527599887278201061
Content-Length: 277

-----------------------------1894318417527599887278201061
Content-Disposition: form-data; name="foo"

a
-----------------------------1894318417527599887278201061
Content-Disposition: form-data; name="bar"

b
-----------------------------1894318417527599887278201061--

URL-encoding isn't efficient for large amounts of binary data. Instead of sending one byte, you have to send three (%xx). By separating each field with an easily-distinguished boundary value (in this case -----------------------------1894318417527599887278201061, but the browser will generate a new one for each request), the browser can send raw binary data. The obvious downside is that it carries some serious overhead for small requests. In this simple example, the multipart request is 25 times larger than the URL-encoded request. Then again, in both cases, the amount of time required to submit the request body will be dwarfed by the amount of time required to open the connection. But that's a story for another day.

like image 95
Mr. DOS Avatar answered Jan 14 '23 22:01

Mr. DOS


Logically speaking, the primary reason you'd switch is when dealing with files (as files can't be encoded over application/x-www-form-urlencoded). Beyond that control, neither has a limitation over the other (it's just simply how it's encoded).

The most notable difference is going to be overhead (in the form of more data being based since multipart/formdata contains details beyond the name/value information).

For example, given the following form:

<form method="POST><!-- exempting encoding/action -->
  <input type="text" name="greeting" value="Hello">
  <input type="text" name="name" value="Brad">
  <input type="submit" value="Submit">
</form>

With the default encoding (application/x-www-form-urlencoded) the response may be:

greeting=Hello&name=Brad

Where as multipart/form-data may look like:

-----------------------------1234567890
Content-Disposition: form-data; name="greeting"

Hello
-----------------------------1234567890
Content-Disposition: form-data; name="name"

Brad
-----------------------------1234567890

As you can see, there is a significant amount of additional overhead using the multipart/form-data enctype, which is generally why it's only included when necessary.

like image 41
Brad Christie Avatar answered Jan 14 '23 20:01

Brad Christie