Загрузка файла HTML5 в Java Servlet

Мой вопрос вроде говорит все. В настоящее время я успешно использую Uploadify (Flash + Ajax) для сервлета (Commons Upload w/OWASP ESAPI overlay), но мне было интересно, как я собираюсь строить поддержку HTML5 или, скорее, HTML5 с поддержкой флэш-памяти.

Я знаю, как работать с HTML5 DnD, но я не могу понять механики соединения Java Servlet и/или бэкэнд. Я искал много мест, но я не могу найти ответы, поэтому любая помощь вообще ценится.

Ответы

Ответ 1

  Я знаю, как заставить работать HTML5 DnD, но не могу понять, как работает соединение с сервлетом Java и/или серверная часть.

Это не отличается от использования обычного <form enctype="multipart/form-data">. Все, что вам нужно сделать, это получить этот код HTML5/JS для отправки запроса multipart/form-data с удаленным файлом, точно такой же тип запроса, какой он был бы отправлен с обычным полем <input type="file">. Я предполагаю, что вы просто не можете понять, как добиться этого с HTML5/JS.

Для этого вы можете использовать новые HTML5 File API, XHR2 FormData и XMLHttpRequestUpload API.

Вот пример того, как должен выглядеть ваш обработчик событий drop:

function dropUpload(event) {
    event.stopPropagation();
    event.preventDefault();

    var formData = new FormData();
    formData.append("file", event.dataTransfer.files[0]);

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "uploadServlet");
    xhr.send(formData);
}

Вот оно. В этом примере предполагается, что сервлет сопоставлен с шаблоном URL-адреса /uploadServlet. В этом примере файл затем доступен в Apache Commons FileUpload обычным способом как экземпляр FileItem с именем поля file.


Для более сложных вещей, таких как прикрепление обработчиков событий для мониторинга прогресса и т.д., Посетите следующие блоги:

Я немного поиграл со следующим SSCCE:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>HTML5 drag'n'drop file upload with Servlet</title>
        <script>
            window.onload = function() {
                var dropbox = document.getElementById("dropbox");
                dropbox.addEventListener("dragenter", noop, false);
                dropbox.addEventListener("dragexit", noop, false);
                dropbox.addEventListener("dragover", noop, false);
                dropbox.addEventListener("drop", dropUpload, false);
            }

            function noop(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            function dropUpload(event) {
                noop(event);
                var files = event.dataTransfer.files;

                for (var i = 0; i < files.length; i++) {
                    upload(files[i]);
                }
            }

            function upload(file) {
                document.getElementById("status").innerHTML = "Uploading " + file.name;

                var formData = new FormData();
                formData.append("file", file);

                var xhr = new XMLHttpRequest();
                xhr.upload.addEventListener("progress", uploadProgress, false);
                xhr.addEventListener("load", uploadComplete, false);
                xhr.open("POST", "uploadServlet", true); // If async=false, then you'll miss progress bar support.
                xhr.send(formData);
            }

            function uploadProgress(event) {
                // Note: does not work with async=false.
                var progress = Math.round(event.loaded / event.total * 100);
                document.getElementById("status").innerHTML = "Progress " + progress + "%";
            }

            function uploadComplete(event) {
                document.getElementById("status").innerHTML = event.target.responseText;
            }
        </script>
        <style>
            #dropbox {
                width: 300px;
                height: 200px;
                border: 1px solid gray;
                border-radius: 5px;
                padding: 5px;
                color: gray;
            }
        </style>
    </head>
    <body>
        <div id="dropbox">Drag and drop a file here...</div>
        <div id="status"></div>
    </body>
</html>

и этот UploadServlet, использующий новый API Servlet 3.0 HttpServletRequest#getPart():

@MultipartConfig
@WebServlet("/uploadServlet")
public class UploadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Part file = request.getPart("file");
        String filename = getFilename(file);
        InputStream filecontent = file.getInputStream();
        // ... Do your file saving job here.

        response.setContentType("text/plain");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write("File " + filename + " successfully uploaded");
    }

    private static String getFilename(Part part) {
        for (String cd : part.getHeader("content-disposition").split(";")) {
            if (cd.trim().startsWith("filename")) {
                String filename = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
                return filename.substring(filename.lastIndexOf('/') + 1).substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
            }
        }
        return null;
    }
}

Смотрите также:

Ответ 2

Вам нужна многокомпонентная конфигурация, такая как:

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

В моем случае это работает только с этой конфигурацией.