11. Getting Data From a Form

../../_images/web-forms.webp

How do we get data that the user has filled out on the front-end, to the back-end? Turns out there are a lot of ways. I have some examples below. What these examples don’t show:

  • How to validate on the front-end (we already covered that)
  • How to validate on the back-end (can’t trust the front end, we’ll get to that later)
  • What to do with the data once you’ve got it
  • Anything to do with security
  • Anything to do with managing logins

We will show:

  • Send data without JavaScript with GET
    • Send via a form
    • Send via a link (e.g. a list of records, we create a different link for each record)
  • Send data without JavaScript with POST
  • Send data with JavaScript via GET
  • Send data with JavaScript via POST
  • Send data with JavaScript via POST and JSON

You can send the data with a GET and a POST method. Data sent via GET is insecure, and will even be part of bookmarks. Only send data this way if the parameter specifies something that should be part of the navigation, like a menu selection. If in doubt, use POST.

11.1. Form Tags

../../_images/tag.svg

If we are sending data via a form, we need to understand how to use the <form> tag. The older way:

Form tag to send data
<form action="api/form_test_servlet" method="get">
   <!-- Form fields go here -->
</form>

What do these fields do?

action="api/form_test_servlet" <-- Where to send the data (our servlet)
method="get"                   <-- How to send the data (get or post)

Another way is to use JavaScript and send the data via AJAX. Since JavaScript controls the sending of the data, we don’t want the form to do anything. We’ll keep the JavaScript in a separate js/form_demo.js file that will attach JavaScript to the button. You can view the output on the JavaScript console.

We have to disable the default action on the form to prevent it from doing anything, so the JavaScript can manage it. It is a weird work-around that doesn’t look very elegant:

Form tag, allowing JavaScript to manage the form
<form action="javascript:void(0);">
   <!-- Form fields go here -->
</form>

It is this action that means “don’t do anything.”

javascript:void(0); <-- Don't do anything during submission.

11.2. Form Fields

This is an example form with an input field, and a submit button. Every field should have a label (line 2). The has a for field that links up to the id of the field it describes (line 3).

The form will work without the label, but the label helps vision-impaired people use a screen reader and figure out what is supposed to go into that box. This will help maximize the number of people your website can serve.

Simple form
1
2
3
4
5
 <form action="api/form_test_servlet" method="get">
     <label for="inputField1a">Input field:</label>
     <input name="fieldname" type="text" id="inputField1a" />
     <input type="submit">
 </form>

We’ll dive into some more complex fields later, out main interest now is to get data to the servlet.

11.3. Creating Forms With HTML

Here’s the HTML. Hook this up to your menu, and make sure you can navigate around. Spend some time studying the HTML.

form_demo.html
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<!DOCTYPE html>

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">

    <link rel="stylesheet"
          href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
          integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
          crossorigin="anonymous">

    <!-- Pick a theme!
         https://www.bootstrapcdn.com/bootswatch/
         -->
    <link rel="stylesheet"
          href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/cosmo/bootstrap.min.css">

    <link rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.6/dropzone.css"
          crossorigin="anonymous" />
    <title>Form Demo</title>

    <style>
        form {
            /* This adds some space under each form, for visual separation. */
            margin-bottom: 35px;
        }
    </style>
</head>

<body>

<!-- Navigation Bar -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Simpson College</a>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item">
                <a class="nav-link" href="index.html">Home</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="api/name_list_get">Name List JSON</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="name_list.html">Name List</a>
            </li>
            <li class="nav-item active">
                <a class="nav-link" href="#">Form Demo <span class="sr-only">(current)</span></a>
            </li>
        </ul>
    </div>
</nav>

<div class="container">

    <!-- This is the important stuff -->
    <h2>Form Demo</h2>

    <p>There are a lot of ways to submit a form.</p>

    <p><b>Method 1:</b></p>
    <p>Classic form submission using "get" method.</p>
    <form action="api/form_test_servlet" method="get">
        <!-- A label isn't necessary for this to work, but it allows vision-impaired people
             and even computers to get what a field is. Otherwise it is just an empty box.
             Get in the habit to add these to all forms, so you can get more customers. -->
        <label for="inputField1a">Input field:</label>
        <input name="fieldname" type="text" id="inputField1a" />
        <input type="submit">
    </form>


    <p><b>Method 1, fancied up with Bootstrap:</b></p>
    <p>Classic form submission using "get" method.</p>
    <form action="api/form_test_servlet" method="get">
        <div class="form-group col-md-4">
            <label for="inputField1b">Input field:</label>
            <input name="fieldname" type="text" class="form-control" id="inputField1b" />
        </div>
        <input class="btn btn-primary" type="submit" value="Go!">
    </form>

    <p><b>Method 2:</b></p>
    <p>Form submission using "get" method as a link.</p>
    <form action="api/form_test_servlet" method="get">
        <ul>
            <li><a href="api/form_test_servlet?fieldname=a">Field a</a></li>
            <li><a href="api/form_test_servlet?fieldname=b">Field b</a></li>
        </ul>
    </form>

    <p><b>Method 3:</b></p>
    <p>Classic form submission using "post" method.</p>
    <form action="api/form_test_servlet" method="post">
        <input name="fieldname" type="text" />
        <input type="submit">
    </form>

    <p><b>Method 4:</b></p>
    <p>JavaScript/AJAX/jQuery form submission using "get" method.</p>
    <p>Check JavaScript console for the result.</p>
    <form action="javascript:void(0);">
        <input id="jqueryGetField" name="fieldname" type="text" />
        <button id="jqueryGetButton">Submit</button>
    </form>

    <p><b>Method 5:</b></p>
    <p>JavaScript/AJAX/jQuery form submission using "post" method.</p>
    <p>Check JavaScript console for the result.</p>
    <form action="javascript:void(0);">
        <input id="jqueryPostField" name="fieldname" type="text" />
        <button id="jqueryPostButton">Submit</button>
    </form>

    <p><b>Method 6:</b></p>
    <p>JavaScript/AJAX/jQuery/JSON-Binding form submission by posting parameterless JSON data.</p>
    <form action="javascript:void(0);">
        <input id="jqueryPostJSONField" name="fieldname" type="text" />
        <button id="jqueryPostJSONButton">Submit</button>
    </form>

    <h3>Checkboxes</h3>

    <form action="api/form_test_checkbox_servlet">
        <input type="checkbox" name="vehicle" value="Skateboard">Skateboard<br/>
        <input type="checkbox" name="vehicle" value="Bike">Bike<br/>
        <input type="checkbox" name="vehicle" value="Car">Car<br/>
        <input type="checkbox" name="vehicle" value="Balloon">Balloon<br/>
        <input type="submit">
    </form>

    <h3>File Upload</h3>
    <p><b>File Upload - Old Style</b></p>
    <form action="api/form_test_file_servlet" method="post" enctype="multipart/form-data">
        <input type="text" name="description" placeholder = "File description"/>
        <input type="file" name="file">
        <input type="submit">
    </form>

    <p><b>File Upload - Drag and Drop</b></p>
    <form action="api/form_test_file_servlet"
          class="dropzone"
          id="myDropzone">
        <div class="fallback">
            <input name="file" type="file" multiple />
        </div>
    </form>

</div>

<!-- Load JavaScript -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
        integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
        crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
        integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"
        crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.6/min/dropzone.min.js"
        crossorigin="anonymous"></script>
<script type="text/javascript" src="js/form_demo.js"></script>
</body>
</html>

11.4. Java Servlet for Non-JSON Requests

We need a servlet to receive the data! Let’s create a new servlet, called FormTestServlet.

This servlet handles the first two non-JavaScript examples, and the next two JavaScript examples. It not handle the JSON example.

FormTestServlet.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package edu.simpson.cis320.crud_app;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "FormTestServlet", value = "/api/form_test_servlet")
public class FormTestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // You can output in any format, text/JSON, text/HTML, etc. We'll keep it simple
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        // Print that this is a get, not a post
        out.println("Get");

        // Grab the data we got via a parameter
        String fieldname = request.getParameter("fieldname");

        // Just print the data out to confirm we got it.
        out.println("fieldname='"+fieldname+"'");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // You can output in any format, text/JSON, text/HTML, etc. We'll keep it simple
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        // Print that this is a post
        out.println("Post");

        // Grab the data we got via a parameter
        String fieldname = request.getParameter("fieldname");

        // Just print the data out to confirm we got it.
        out.println("fieldname='"+fieldname+"'");
    }
}

Enter the servlet. Study the code. Run it against the first form. You should get something like:

Get
fieldname='hi'

At this point, methods 1, 2, and 3 should all work. Notice the URLs on the get methods and how they are constructed:

api/form_test_servlet?fieldname=hi

Try entering spaces, quotes, ampersands, and other characters to see how they get encoded. How do we encode multiple fields?

11.5. JavaScript

Modern forms process data with JavaScript instead. We can add JavaScript to our form. The HTML above tries to load JavaScript from js/form_demo.py.

11.5.1. JavaScript AJAX Get

Add in some JavaScript to send data via “GET” to our servlet:

JavaScript to process Method 4. AJAX GET
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/* Method 4: Use an AJAX Get */
function jqueryGetButtonAction() {

    // URL where our servlet is at
    let url = "api/form_test_servlet";
    // Use jQuery to grab the dataout of the field
    let myFieldValue = $("#jqueryGetField").val();
    // Create a JSON object with field names and field values
    let dataToServer = { fieldname : myFieldValue };

    // Send the request to the servlet
    $.get(url, dataToServer, function (dataFromServer) {
        // This happens when we are don
        console.log("Finished calling servlet.");
        console.log(dataFromServer);
    });
}

// Hook the function above to the 'submit' button for the Method 4 form
let jqueryGetButton = $('#jqueryGetButton');
jqueryGetButton.on("click", jqueryGetButtonAction);

Try getting this to work for Method 4. It doesn’t do anything visible, you’ll need to open the console to see the output. We’re keeping things simple in this lesson, focusing only on getting the data to and from the server.

11.5.2. JavaScript AJAX POST

Sending the data via POST instead of GET is super-easy. Just change get to post. Remember, data sent via get is not secure, and only use get if you want it as part of a navigation link or similar.

JavaScript to process Method 5. AJAX POST
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* Method 5: Use an AJAX Post */
function jqueryPostButtonAction() {

    let url = "api/form_test_servlet";
    let myFieldValue = $("#jqueryPostField").val();
    let dataToServer = { fieldname : myFieldValue };

    $.post(url, dataToServer, function (dataFromServer) {
        console.log("Finished calling servlet.");
        console.log(dataFromServer);
    });
}
let jqueryPostButton = $('#jqueryPostButton');
jqueryPostButton.on("click", jqueryPostButtonAction);

The JavaScript only handles the last three forms. The first two show how to do classic form submission with no JavaScript.

js/form_demo.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!-- AJAX Get -->
function jqueryGetButtonAction() {

    var url = "api/form_test_servlet";
    var myFieldValue = $("#jqueryGetField").val();
    var dataToServer = { fieldname : myFieldValue };

    $.get(url, dataToServer, function (dataFromServer) {
        console.log("Finished calling servlet.");
        console.log(dataFromServer);
    });
}
var jqueryGetButton = $('#jqueryGetButton');
jqueryGetButton.on("click", jqueryGetButtonAction);

<!-- AJAX Post -->
function jqueryPostButtonAction() {

    var url = "api/form_test_servlet";
    var myFieldValue = $("#jqueryPostField").val();
    var dataToServer = { fieldname : myFieldValue };

    $.post(url, dataToServer, function (dataFromServer) {
        console.log("Finished calling servlet.");
        console.log(dataFromServer);
    });
}
var jqueryPostButton = $('#jqueryPostButton');
jqueryPostButton.on("click", jqueryPostButtonAction);

<!-- AJAX Post using JSON data -->
function jqueryPostJSONButtonAction() {

    var url = "api/form_test_json_servlet";
    var myFieldValue = $("#jqueryPostJSONField").val();
    var dataToServer = { fieldname : myFieldValue };

    $.ajax({
        type: 'POST',
        url: url,
        data: JSON.stringify(dataToServer),
        success: function(dataFromServer) {
            console.log(dataFromServer);
        },
        contentType: "application/json",
        dataType: 'text' // Could be JSON or whatever too
    });
}
var jqueryPostJSONButton = $('#jqueryPostJSONButton');
jqueryPostJSONButton.on("click", jqueryPostJSONButtonAction);

Dropzone.options.myDropzone = {
    init: function() {
        this.on("success", function(file, response) {
            console.log(response);
        });
    }
};

11.6. Using JSON For Data

All the methods above are common, but now considered “old school.” (Although, we might use GET to construct URL links still, as shown in Method 2.)

Now, we normally send the data via POST in a JSON format. To do that we’ll need a different Servlet. We’ll also need a new JavaScript function.

11.6.1. Java for JSON Requests

Here is a simple business object we’ll put our JSON data into.

11.6.1.1. Business Object

FormTestObject.java
1
2
3
4
5
package edu.simpson.cis320.crud_app;

public class FormTestObject {
    public String fieldname;
}

11.6.1.2. Servlet

Here’s how we get the JSON data.

FormTestJSONServlet.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
Show how to handle posts of JSON data
Method 6
 */

package edu.simpson.cis320.crud_app;

import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;

@WebServlet(name = "NameListGetServlet", value = "/api/form_test_json_servlet")
public class FormTestJSONServlet extends HttpServlet {
    private final static Logger log = Logger.getLogger(FormTestJSONServlet.class.getName());

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        log.log(Level.INFO, "doPost for FormTestJSONServlet");

        // You can output in any format, text/JSON, text/HTML, etc. We'll keep it simple
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        // Open the request for reading. Read in each line, put it into a string.
        // Yes, I think there should be an easier way.
        java.io.BufferedReader in = request.getReader();
        String requestString = new String();
        for (String line; (line = in.readLine()) != null; requestString += line);

        // Log the string we got as a request, just as a check
        log.log(Level.INFO, requestString);

        // Great! Now we want to parse the object, and pop it into our business object. Field
        // names have to match. That's the magic.
        Jsonb jsonb = JsonbBuilder.create();
        FormTestObject formTestObject = jsonb.fromJson(requestString, FormTestObject.class);

        // Log info as a check
        log.log(Level.INFO, "Object test: "+formTestObject.fieldname);

        // Send something back to the client. Really, we should send a JSON, but
        // we'll keep things simple.
        out.println("Object test: "+formTestObject.fieldname);
    }

}

11.6.2. JavaScript for JSON Requests

The JavaScript is very similar to before, except we will data out data and call JSON.stringify to turn the JSON object into a string. We then send the whole chunk of JSON data over instead of a set of parameters/values. We use jQuery’s $.ajax command.

/* Method 6: AJAX Post using JSON data */
function jqueryPostJSONButtonAction() {

    let url = "api/form_test_json_servlet";
    let myFieldValue = $("#jqueryPostJSONField").val();
    let dataToServer = { fieldname : myFieldValue };

    $.ajax({
        type: 'POST',
        url: url,
        data: JSON.stringify(dataToServer),
        success: function(dataFromServer) {
            console.log(dataFromServer);
        },
        contentType: "application/json",
        dataType: 'text' // Could be JSON or whatever too
    });
}
let jqueryPostJSONButton = $('#jqueryPostJSONButton');
jqueryPostJSONButton.on("click", jqueryPostJSONButtonAction);

Go ahead and give it a try. This is the pattern you should follow most of the time. It is just three parts: java business object, java servlet, and front-end javascript. Copy/paste from the template and expand to manage the fields you want.

11.7. Checkboxes

Checkboxes on forms are weird. They deserve their own section. A URL with all checkboxes checked could look like:

http://localhost:8080/api/form_test_checkbox_servlet?vehicle=Skateboard&vehicle=Bike&vehicle=Car&vehicle=Balloon

See how “vehicle” appears multiple times? And if none of them are checked:

http://localhost:8080/api/form_test_checkbox_servlet

Nothing appears at all. Like it wasn’t even there on the form. Here’s an example how to process them:

FormTestCheckboxServlet.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package edu.simpson.cis320.crud_app;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "FormTestCheckboxServlet", value = "/api/form_test_checkbox_servlet")
public class FormTestCheckboxServlet extends HttpServlet {

    /* Handle Post or Get requests */
    private void processPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        // Grab the data we got via a parameter
        String [] vehicles = request.getParameterValues("vehicle");

        // If nothing is checked, we get a null. We do not get a list with
        // no items.
        if(vehicles == null) {
            out.println("There were no vehicles checked.");
        } else {
            // List each vehicle checked.
            out.println("List of vehicles");

            for (int i = 0; i < vehicles.length; i++) {
                // Just print the data out to confirm we got it.
                out.println("vehicle='" + vehicles[i] + "'");
            }
            out.println("Done with the list");
        }
    }

    /* I don't care if it is a get or a post, do the same for both. */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.processPost(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.processPost(request, response);
    }
}

11.8. Files

File handling requires a multi-part upload. Not only do you have to write servlet code to handle it, you need to specify that your code can take the file. We’ll add a @MultipartConfig directive right before we declare the servlet. It takes the following parameters:

  • location: An absolute path to a directory on the file system. The location attribute does not support a path relative to the application context. This location is used to store files temporarily while the parts are processed or when the size of the file exceeds the specified fileSizeThreshold setting. The default location is “”.
  • file-size-threshold: The file size in bytes after which the file will be temporarily stored on disk. The default size is 0 bytes.
  • max-file-size: The maximum size allowed for uploaded files, in bytes. If the size of any uploaded file is greater than this size, the web container will throw an exception (IllegalStateException). The default size is unlimited.
  • max-request-size: The maximum size allowed for a multipart/form-data request, in bytes. The web container will throw an exception if the overall size of all uploaded files exceeds this threshold. The default size is unlimited.

Finally, it will look like:

@MultipartConfig(fileSizeThreshold = 1024 * 1024,
        maxFileSize = 1024 * 1024 * 5,
        maxRequestSize = 1024 * 1024 * 5 * 5)

If you don’t add this to your servlet, you’ll find that you can’t pull the fields and you’ll get no error. It is an annoying error to chase down.

Here’s the full servlet:

FormTestFileServlet.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package edu.simpson.cis320.crud_app;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "FormTestServlet", value = "/api/form_test_file_servlet")
@MultipartConfig(fileSizeThreshold = 1024 * 1024,
        maxFileSize = 1024 * 1024 * 5,
        maxRequestSize = 1024 * 1024 * 5 * 5)
public class FormTestFileServlet  extends HttpServlet {

    /* Utility function to parse out the file name that was uploaded. */
    private String extractFileName(Part part) {
        String contentDisp = part.getHeader("content-disposition");
        String[] items = contentDisp.split(";");
        for (String s : items) {
            if (s.trim().startsWith("file")) {
                return s.substring(s.indexOf("=") + 2, s.length()-1);
            }
        }
        return "";
    }

    /* Process an uploaded file */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // You can output in any format, text/JSON, text/HTML, etc. We'll keep it simple
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        // This is just here to show you can upload form fields in addition to the file
        String description = request.getParameter("description");
        out.println("Description: "+description);

        // If you have a control with multiple files that can be uploaded, there is a "getParts" method
        Part filePart = request.getPart("file"); // Retrieves <input type="file" name="file">
        if(filePart != null) {
            // We get this long complicated line here:
            out.println("content-disposition: " + filePart.getHeader("content-disposition"));

            // This function pulls the file name out of that.
            String fileName = extractFileName(filePart);

            // Print the file name
            out.println(fileName);

            // Write the file here.
            // I don't use the file name, because I haven't shown how to protect against
            // "directory traversal" yet.
            filePart.write("C:/temp/myfile.txt");
        } else {
            out.println("No part");
        }
        out.println("Done");
    }
}

11.8.1. Drag and Drop

If you use a library, making your website support drag/drop uploading isn’t hard. In the example I use the same servlet, but use a DropZone library I found (and CSS) to help process the request.