What does enctype='multipart/form-data' mean?
When you make a POST request, you have to encode the data that forms the body of the request in some way.
HTML forms provide three methods of encoding.
application/x-www-form-urlencoded
(the default)multipart/form-data
text/plain
Work was being done on adding application/json
, but that has been abandoned.
(Other encodings are possible with HTTP requests generated using other means than an HTML form submission. JSON is a common format for use with web services and some still use SOAP.)
The specifics of the formats don't matter to most developers. The important points are:
- Never use
text/plain
.
When you are writing client-side code:
- use
multipart/form-data
when your form includes any<input type="file">
elements - otherwise you can use
multipart/form-data
orapplication/x-www-form-urlencoded
butapplication/x-www-form-urlencoded
will be more efficient
When you are writing server-side code:
- Use a prewritten form handling library
Most (such as Perl's CGI->param
or the one exposed by PHP's $_POST
superglobal) will take care of the differences for you. Don't bother trying to parse the raw input received by the server.
Sometimes you will find a library that can't handle both formats. Node.js's most popular library for handling form data is body-parser which cannot handle multipart requests (but has documentation that recommends some alternatives which can).
If you are writing (or debugging) a library for parsing or generating the raw data, then you need to start worrying about the format. You might also want to know about it for interest's sake.
application/x-www-form-urlencoded
is more or less the same as a query string on the end of the URL.
multipart/form-data
is significantly more complicated but it allows entire files to be included in the data. An example of the result can be found in the HTML 4 specification.
text/plain
is introduced by HTML 5 and is useful only for debugging — from the spec: They are not reliably interpretable by computer — and I'd argue that the others combined with tools (like the Network Panel in the developer tools of most browsers) are better for that).
What is the right way to POST multipart/form-data using curl?
The following syntax fixes it for you:
curl -v -F key1=value1 -F upload=@localfilename URL
How to send multipart/form-data request using Postman
UPDATE: I have created a video on sending multipart/form-data requests to explain this better.
Actually, Postman can do this.
Full example:
You DON'T need to add any headers, Postman will do this for you automatically.
Make sure you check the comment from @maxkoryukov
Be careful with explicit Content-Type header. Better - do not set it's
value, the Postman is smart enough to fill this header for you. BUT,
if you want to set the Content-Type: multipart/form-data - do not
forget about boundary field.
405 Error : multipart/form-data with Spring
This was the solution that I found from Antonio112009's answer
SOLUTION
@PostMapping(value = "/submitForm")
public ResponseEntity<?> userRegistration(
@RequestParam("user") String user,
@RequestParam(value = "files", required = false) List<MultipartFile> files) {
ObjectMapper obj = new ObjectMapper();
User user = new User();
.
.
.
}
POST data using the Content-Type multipart/form-data
Here's some sample code.
In short, you'll need to use the mime/multipart
package to build the form.
package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/http/httptest"
"net/http/httputil"
"os"
"strings"
)
func main() {
var client *http.Client
var remoteURL string
{
//setup a mocked http client.
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, err := httputil.DumpRequest(r, true)
if err != nil {
panic(err)
}
fmt.Printf("%s", b)
}))
defer ts.Close()
client = ts.Client()
remoteURL = ts.URL
}
//prepare the reader instances to encode
values := map[string]io.Reader{
"file": mustOpen("main.go"), // lets assume its this file
"other": strings.NewReader("hello world!"),
}
err := Upload(client, remoteURL, values)
if err != nil {
panic(err)
}
}
func Upload(client *http.Client, url string, values map[string]io.Reader) (err error) {
// Prepare a form that you will submit to that URL.
var b bytes.Buffer
w := multipart.NewWriter(&b)
for key, r := range values {
var fw io.Writer
if x, ok := r.(io.Closer); ok {
defer x.Close()
}
// Add an image file
if x, ok := r.(*os.File); ok {
if fw, err = w.CreateFormFile(key, x.Name()); err != nil {
return
}
} else {
// Add other fields
if fw, err = w.CreateFormField(key); err != nil {
return
}
}
if _, err = io.Copy(fw, r); err != nil {
return err
}
}
// Don't forget to close the multipart writer.
// If you don't close it, your request will be missing the terminating boundary.
w.Close()
// Now that you have a form, you can submit it to your handler.
req, err := http.NewRequest("POST", url, &b)
if err != nil {
return
}
// Don't forget to set the content type, this will contain the boundary.
req.Header.Set("Content-Type", w.FormDataContentType())
// Submit the request
res, err := client.Do(req)
if err != nil {
return
}
// Check the response
if res.StatusCode != http.StatusOK {
err = fmt.Errorf("bad status: %s", res.Status)
}
return
}
func mustOpen(f string) *os.File {
r, err := os.Open(f)
if err != nil {
panic(err)
}
return r
}
Empty $request- request and $request- files with multipart/form-data
DO NOT specify the Content-Type
header yourself, when trying to make such a multipart request. That header needs to include the boundary value (so that the receiver will know how to parse this request) - if you specify it yourself, as just multipart/form-data
, then that will be missing.
These request libraries usually know how to properly set it on their own, based on that you are passing in a FormData instance.
Why not use enctype= multipart/form-data always?
From the RFC that defines multipart/form-data
:
Many web applications use the "application/x-www-form-urlencoded"
method for returning data from forms. This format is quite compact,
for example:
name=Xavier+Xantico&verdict=Yes&colour=Blue&happy=sad&Utf%F6r=Send
However, there is no opportunity to label the enclosed data with a
content type, apply a charset, or use other encoding mechanisms.Many form-interpreting programs (primarily web browsers) now
implement and generate multipart/form-data, but a receiving
application might also need to support the
"application/x-www-form-urlencoded" format.
Aside from letting you upload files, multipart/form-data
also allows you to use other charsets and encoding mechanisms. So the only reasons not to use it are:
If you want to save a bit of bandwidth (bearing in mind that this becomes much less of an issue if the request body is compressed).
If you need to support really old clients that can't handle file uploads and only know
application/x-www-form-urlencoded
, or that have issues handling anything other than ASCII.
Get key-value pairs from multipart/form-data HTTP POST request in Camel
For the sake of clarity, as the proposed solution here above seems to work, a bit more explanations (although it is more a workaround than a solution):
Starting from:
Map<String, Attachment> attachmentObjects = attachmentMessage.getAttachmentObjects();
It is possible to browse all map entries, and for each found Attachment
object, examine the attachment headers using getHeaderNames()
, among other the 'Content-Disposition' one:
Content-Disposition: form-data; name="data"; filename="data-file.json"
which can finally be parsed to grab the form name ('data' in this example).
Not straightforward true, but this apparently works...
Related Topics
How to Make ≪Div≫ Fill ≪Td≫ Height
How Make Background Image on Newsletter in Outlook
How to Style Part of an Input Field'S Value
How to Display Raw HTML Code in Pre or Something Like It But Without Escaping It
Swift: Display HTML Data in a Label or Textview
How to Run an External Program, E.G. Notepad, Using Hyperlink
Font Rendering/Line-Height Issue on MAC/Pc (Outside of Element)
Why Are Button's Discouraged from Navigation
Use CSS to Remove the Space Between Images
Flexbox Column-Reverse in Firefox, Edge and Ie
Regex Replace Text Outside HTML Tags
Why Is There a Vertical Scroll Bar If Parent and Child Have the Same Height
How to Align Two Divs Horizontally
HTML Select Form with Option to Enter Custom Value
Empty Vertical Space Between Columns in Bootstrap 4