Html5 Drag and Drop File Upload to Java Servlet

HTML5 drag and drop file upload to Java Servlet

I know how to get the HTML5 DnD working, but I can't quite figure out the mechanics of a Java Servlet connection and/or backend.

It's not different from when using a regular <form enctype="multipart/form-data">. All you need to do is to get that HTML5/JS code to send a multipart/form-data request with the dropped file, exactly the same kind of request as it would have been sent with a regular <input type="file"> field. I'll assume that you just can't figure out how to achieve exactly that with HTML5/JS.

You can utilize the new HTML5 File API, XHR2 FormData and XMLHttpRequestUpload APIs for this.

Here's a kickoff example of how your drop event handler should look like:

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);
}

That's it. This example assumes that the servlet is mapped on a URL pattern of /uploadServlet. In this example, the file is then available in Apache Commons FileUpload the usual way as a FileItem instance with a field name of file.


For more advanced stuff like attaching event handlers for monitoring the progress and like, checkout the following blogs:

  • HTML5 Drag and Drop Upload and File API Tutorial
  • HTML5 File Upload With Progress

I've played somewhat around it with the following 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: doesn't 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>

and this UploadServlet utilizing the new Servlet 3.0 HttpServletRequest#getPart() API:

@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;
}
}

See also:

  • How to upload files to server using JSP/Servlet?

Uploading a file from a php page to a Java Servlet

PHP is not relevant. It's all about its generated HTML output. Just make sure that the PHP-generated form look like this (open page in browser, rightclick and View Source to verify it):

<form action="http://example.com/uploadservlet" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" />
</form>

For the servlet end, just check How to upload files to server using JSP/Servlet?

If you really intend to use JavaScript to send the POST request asynchronously, checkout the jQuery Form plugin which simulates asynchronous file uploads by an <iframe> hack, or HTML5/XHR2 which supports asynchronous file uploads natively.

multiple file upload using html5 drag-and-drop fails as multiple files get same content

I spent sometimes this morning in analyzing the same code from html5uploader. With some lucks, I found the root cause.

Change reader = new FileReader(); to var reader = new FileReader(); should solve the issue.

I bet this is because javascripts behaviour of auto-declaring undeclared variable as global variable. This caused the reader variable being reused by all the uploade(file) calls when more than one file is dropped to the browser.

Cheers!



Related Topics



Leave a reply



Submit