Feb 21st, 2017 - written by Kimserey with .
When building websites, chances are that you will need to gather data from your users. The most common way to gather data is via a form. But after gathering the data, there are two ways to submit it from the browser to your server; using a HTML form or using an Ajax call
Today we will see the differences and how we can implement it.
Before hand, I have created a simple server which has a single endpoint accepting a POST.
1
2
3
4
5
type EndPoint =
| [<EndPoint "POST /upload">] Upload
let Main =
Application.MultiPage (fun ctx -> function Upload -> Content.Text "Received")
Next we can create a simple form with one an input and button to submit.
1
2
3
4
<form method="post" action="/upload">
<input name="my-data" type="text" />
<button type="submit">Submit</button>
</form>
The action
is the url to post to.
The method
is the Http method.
When we press the submit, the form is submitted and we can see from Chrome that the data have been submitted using a POST and that the content type is x-www-form-urlencoded.
1
2
3
4
Content-Type:application/x-www-form-urlencoded
Form Data
my-data:test
Url encoded means that the content of the form has been encoded in the url and posted to the action specified. This is the default behavior of a form submit.
But if we need to send a file, we will not be able to url encode the file, we need to send it as form-data
.
Let’s start by adding a file input:
1
2
3
4
5
<form method="post" action="/upload" enctype="multipart/form-data">
<input name="my-data" type="text" />
<input type="file" name="some-file" />
<button type="submit">Submit</button>
</form>
To tell the browser to submit as form-data we need to specify the encoding type enctype="multipart/form-data"
.
Now when we submit we can see that the data has been sent as multipart form data.
And the content type also include boundary=XXX
which lets the server know the boundary delimiting the data in the body of the request.
1
2
3
4
5
6
7
8
9
10
11
12
13
Content-Type:multipart/form-data; boundary=----WebKitFormBoundary23lA5KSmXMXrKcOe
Request payload:
------WebKitFormBoundary23lA5KSmXMXrKcOe
Content-Disposition: form-data; name="my-data"
hello world
------WebKitFormBoundary23lA5KSmXMXrKcOe
Content-Disposition: form-data; name="some-file"; filename="Untitled.png"
Content-Type: image/png
------WebKitFormBoundary23lA5KSmXMXrKcOe--
And from the server side, we can see that we receive a file in the context request.
To prevent double submit (due to the page POST’ing the request being loaded), we can implement the POST/REDIRECT/GET logic (PRG).
In the era of SPAs, lot of websites now do everything via JavaScript and Ajax in particular to submit data. Let’s see how we can achieve that in JS.
Submitting data by Ajax allows to submit a json object which can be easily deserialized on our server. To do that we can intercept the submission when the button is pressed and gather all data on submit and serialize the content of the form.
1
2
3
4
5
<form id="form">
<input name="data-1" type="text" />
<input name="data-2" type="text" />
<button id="ajaxForm">Submit</button>
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
(function () {
$("#ajaxForm").click(function (e) {
e.preventDefault();
var json = JSON.stringify($("#form").serializeArray());
$.ajax({
type: "post",
url: "/upload",
data: json,
contentType: "application/json",
success: function () { }
});
})
})()
Clicking on the submit button will invoke the click handle and submit data as json
:
1
2
3
Content-Type:application/json
[{name: "data-1", value: "test1"}, {name: "data-2", value: "test2"}]
serializeArray
is quite clever as it selects input with a name
and the value
assigned and place it into a serializable key value list.
https://api.jquery.com/serializeArray/
If we need to submit a file here, we will not be able to use Json
and same as previously, we will need to use form data
.
To do that we can build the form data using FormData
and .append()
.
1
2
3
4
5
6
<form id="form2">
<input name="data-1" type="text" />
<input name="data-2" type="text" />
<input type="file" name="some-file" />
<button id="ajaxFormFormData">Submit</button>
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$("#ajaxFormFormData").click(function (e) {
e.preventDefault();
var form = $("#form2");
var fd = new FormData();
$.each(form.serializeArray(), function (index, val) {
fd.append(val.name, val.value)
});
fd.append('file', form.children('input[type=file]')[0].files[0]);
$.ajax({
type: "post",
url: "/upload",
data: fd,
contentType: false,
processData: false,
success: function () { }
});
});
Here we append all the data and the files to the form data. Next we pass the form data to the Ajax post and set the processData
to false and contentType
to false - setting contentType
to false will have the multipart content type and boundary automatically set for us.
Now when we submit the form, the content plus the files will be sent as multipart/form-data
.
1
2
3
4
5
6
7
8
9
10
11
12
13
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryTCQcqMA9mCM3QP5H
------WebKitFormBoundaryTCQcqMA9mCM3QP5H
Content-Disposition: form-data; name="data-1"
test
------WebKitFormBoundaryTCQcqMA9mCM3QP5H
Content-Disposition: form-data; name="data-2"
test
------WebKitFormBoundaryTCQcqMA9mCM3QP5H
Content-Disposition: form-data; name="file"; filename="my_image.png"
Content-Type: image/png
And that’s it, those are the main ways we can submit data from the client to the server!
Today we saw how we could submit data from the client to the server via a Http POST. We saw how we could do it using classic HTML forms then we learnt how we could do it straight from JavaScript with Ajax. We also learnt the different content type and how to use them. I hope this post was helpful! As usual if you have any comments leave it here or hit me on Twitter @Kimserey_Lam. See you next time!
Support me by visting my website. Thank you!
Support me by downloading my app BASKEE. Thank you!
Support me by downloading my app EXPENSE KING. Thank you!
Support me by downloading my app RECIPE KEEPER. Thank you!