jQuery-File-Upload js library is “so far” the most elegant, smart, simple..etc js library I have used to upload files. Simply it is amazing. It supports async upload “Ajax”, multiple files upload, drag&drop, progress update and a lot more. Here we will see how to upload multiple files to Java “Servlet” app and how to deal with uploaded files using Java Servlet API or Apache FileUpload Library. Bootstrap has been used in this example to make the UI more attractive.
Image may be NSFW.
Clik here to view.
Objectives:
- How to upload single or multiple files using jquery.fileupload.js?
- How to receive uploaded files using Java Servlet API?
- How to receive uploaded files using Apache FileUpload lib?
Environment & Tools
- Eclipse
- Maven
- Jetty (jetty-maven-plugin 9.x) or any other server supporting servlet 3.0
- Browser (FireFox or Chrome)
Libraries:
Server side Java Libraries
- Java Servlet API 3.0
- Apache FileUpload
- Jackson
- List of jar files: .classpath
- List of Maven dependencies: pom.xml
Client side Javascript libraries
( 1 ) Project Structure Image may be NSFW.
Clik here to view.
( 2 ) Server-Side “Back-end”
- FileUploadServlet.java
- MultipartRequestHandler.java
- FileMeta.java
- web.xml
- /src/main/java/com/hmkcode/FileUploadServlet.java
- FileUploadServlet.java is the servlet that will receive client request
- It has two method, doPost() to handle file upload requests and doGet() to handle file download requests.
- doPost() response content is in JSON format.
package com.hmkcode; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.LinkedList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; import com.hmkcode.vo.FileMeta; //this to be used with Java Servlet 3.0 API @MultipartConfig public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; // this will store uploaded files private static List<FileMeta> files = new LinkedList<FileMeta>(); /*************************************************** * URL: /upload * doPost(): upload the files and other parameters ****************************************************/ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ // 1. Upload File Using Java Servlet API //files.addAll(MultipartRequestHandler.uploadByJavaServletAPI(request)); // 1. Upload File Using Apache FileUpload files.addAll(MultipartRequestHandler.uploadByApacheFileUpload(request)); // Remove some files while(files.size() > 20) { files.remove(0); } // 2. Set response type to json response.setContentType("application/json"); // 3. Convert List<FileMeta> into JSON format ObjectMapper mapper = new ObjectMapper(); // 4. Send resutl to client mapper.writeValue(response.getOutputStream(), files); } /*************************************************** * URL: /upload?f=value * doGet(): get file of index "f" from List<FileMeta> as an attachment ****************************************************/ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ // 1. Get f from URL upload?f="?" String value = request.getParameter("f"); // 2. Get the file of index "f" from the list "files" FileMeta getFile = files.get(Integer.parseInt(value)); try { // 3. Set the response content type = file content type response.setContentType(getFile.getFileType()); // 4. Set header Content-disposition response.setHeader("Content-disposition", "attachment; filename=\""+getFile.getFileName()+"\""); // 5. Copy file inputstream to response outputstream InputStream input = getFile.getContent(); OutputStream output = response.getOutputStream(); byte[] buffer = new byte[1024*10]; for (int length = 0; (length = input.read(buffer)) > 0;) { output.write(buffer, 0, length); } output.close(); input.close(); }catch (IOException e) { e.printStackTrace(); } } }
- /src/main/java/com/hmkcode/MultipartRequestHandler.java
- MultipartRequestHandler.java will get uploaded files out of request object in one of two ways.
- uploadByJavaServletAPI(): it gets all uploaded files using Java Servlet API. Note, this work with Servlet 3.0
- uploadByApacheFileUpload(): it gets all uploaded files using Apache FileUpload lib.
package com.hmkcode; import java.io.IOException; import java.util.Collection; import java.util.LinkedList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.Part; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import com.hmkcode.vo.FileMeta; public class MultipartRequestHandler { public static List<FileMeta> uploadByJavaServletAPI(HttpServletRequest request) throws IOException, ServletException{ List<FileMeta> files = new LinkedList<FileMeta>(); // 1. Get all parts Collection<Part> parts = request.getParts(); // 2. Get paramter "twitter" String twitter = request.getParameter("twitter"); // 3. Go over each part FileMeta temp = null; for(Part part:parts){ // 3.1 if part is multiparts "file" if(part.getContentType() != null){ // 3.2 Create a new FileMeta object temp = new FileMeta(); temp.setFileName(getFilename(part)); temp.setFileSize(part.getSize()/1024 +" Kb"); temp.setFileType(part.getContentType()); temp.setContent(part.getInputStream()); temp.setTwitter(twitter); // 3.3 Add created FileMeta object to List<FileMeta> files files.add(temp); } } return files; } public static List<FileMeta> uploadByApacheFileUpload(HttpServletRequest request) throws IOException, ServletException{ List<FileMeta> files = new LinkedList<FileMeta>(); // 1. Check request has multipart content boolean isMultipart = ServletFileUpload.isMultipartContent(request); FileMeta temp = null; // 2. If yes (it has multipart "files") if(isMultipart){ // 2.1 instantiate Apache FileUpload classes DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); // 2.2 Parse the request try { // 2.3 Get all uploaded FileItem List<FileItem> items = upload.parseRequest(request); String twitter = ""; // 2.4 Go over each FileItem for(FileItem item:items){ // 2.5 if FileItem is not of type "file" if (item.isFormField()) { // 2.6 Search for "twitter" parameter if(item.getFieldName().equals("twitter")) twitter = item.getString(); } else { // 2.7 Create FileMeta object temp = new FileMeta(); temp.setFileName(item.getName()); temp.setContent(item.getInputStream()); temp.setFileType(item.getContentType()); temp.setFileSize(item.getSize()/1024+ "Kb"); // 2.7 Add created FileMeta object to List<FileMeta> files files.add(temp); } } // 2.8 Set "twitter" parameter for(FileMeta fm:files){ fm.setTwitter(twitter); } } catch (FileUploadException e) { e.printStackTrace(); } } return files; } // this method is used to get file name out of request headers // 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; } }
- /src/main/java/com/hmkcode/vo/FileMeta.java
FileMeta is just a data model to hold file meta info and content.
package com.hmkcode.vo; import java.io.InputStream; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties({"content"}) public class FileMeta { private String fileName; private String fileSize; private String fileType; private String twitter; private InputStream content; //getters and setters... }
- /src/main/webapp/WEB-INF/web.xml
web.xml defines the servlet. Note, we are usign Servlet 3.0
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <servlet> <servlet-name>upload</servlet-name> <servlet-class>com.hmkcode.FileUploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>upload</servlet-name> <url-pattern>/upload</url-pattern> </servlet-mapping> </web-app>
( 3 ) Client-Side “Front-end”
- index.html
- myuploadfunction.js
- dropzone.css
- /scr/main/webapp/index.html
HTML page structure: header, title, file input, drop zone & uploaded files table.
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>jQuery File Upload Example</title> <script src="js/jquery.1.9.1.min.js"></script> <script src="js/vendor/jquery.ui.widget.js"></script> <script src="js/jquery.iframe-transport.js"></script> <script src="js/jquery.fileupload.js"></script> <!-- bootstrap just to have good looking page --> <script src="bootstrap/js/bootstrap.min.js"></script> <link href="bootstrap/css/bootstrap.css" type="text/css" rel="stylesheet" /> <!-- we code these --> <link href="css/dropzone.css" type="text/css" rel="stylesheet" /> <script src="js/myuploadfunction.js"></script> <!-- header style ignore it --> <link href="css/mystyle.css" rel="stylesheet"> <link href="css/style.css" rel="stylesheet"> </head> <body> <div id="site-title-content"> <h3 class="site-header"><a rel="home" title="HMKCode" href="http://hmkcode.com/"> HMKCode</a> </h3> <h4 class="site-description"> Code First! </h4> </div> <div id="header"> </div> <div class="social-button icon"> <a href="http://www.twitter.com/hmkcode" target="_blank" title="Visit Us On Twitter"><img src="img/twitter.png" style="border:0px;" alt="Visit Us On Twitter"></a> <a href="https://www.facebook.com/pages/HMKCode/157443611098005" target="_blank" title="Visit Us On Facebook"><img src="img/facebook.png" style="border:0px;" alt="Visit Us On Facebook"></a> <a href="https://plus.google.com/b/113117706677442855053/113117706677442855053" target="_blank" title="Visit Us On Google Plus"><img src="img/googleplus.png" style="border:0px;" alt="Visit Us On Google Plus"></a> </div> <h1 style="text-align:center">Servlet jQuery File Upload<br></h1> <!-- user twitter --> <div id="user_twitter"> <span>Your Twitter</span> <div class="input-prepend"> <span class="add-on">@</span> <input class="span2" id="twitter" name="twitter" type="text" placeholder="Username"> </div> </div> <div style="width:700px;padding:20px;S"> <input id="fileupload" type="file" name="files[]" data-url="upload" multiple> <div id="dropzone" class="fade well">Drop files here</div> <div id="progress" class="progress"> <div class="bar" style="width: 0%;"></div> </div> <h5 style="text-align:center"><i style="color:#ccc"><small>Max File Size: 2 Mb - Display last 20 files</small></i></h5> <table id="uploaded-files" class="table"> <tr> <th>File Name</th> <th>File Size</th> <th>File Type</th> <th>Download</th> <th>Uploaded By</th> </tr> </table> </div> </body> </html>
- /scr/main/webapp/js/myuploadfunction.js
This JS function receives servlet JSON response and displays it in a tabular format.
$(function () { $('#fileupload').fileupload({ dataType: 'json', done: function (e, data) { $("tr:has(td)").remove(); $.each(data.result, function (index, file) { $("#uploaded-files").append( $('<tr/>') .append($('<td/>').text(file.fileName)) .append($('<td/>').text(file.fileSize)) .append($('<td/>').text(file.fileType)) .append($('<td/>').html("<a href='upload?f="+index+"'>Click</a>")) .append($('<td/>').text("@"+file.twitter)) )//end $("#uploaded-files").append() }); }, progressall: function (e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); $('#progress .bar').css( 'width', progress + '%' ); }, dropZone: $('#dropzone') }).bind('fileuploadsubmit', function (e, data) { // The example input, doesn't have to be part of the upload form: var twitter = $('#twitter'); data.formData = {twitter: twitter.val()}; }); });
- /scr/main/webapp/css/dropzone.css
This CSS is to style the drop zone
#dropzone { background: #ccccc; width: 150px; height: 50px; line-height: 50px; text-align: center; font-weight: bold; } #dropzone.in { width: 600px; height: 200px; line-height: 200px; font-size: larger; } #dropzone.hover { background: lawngreen; } #dropzone.fade { -webkit-transition: all 0.3s ease-out; -moz-transition: all 0.3s ease-out; -ms-transition: all 0.3s ease-out; -o-transition: all 0.3s ease-out; transition: all 0.3s ease-out; opacity: 1; }
( 4 ) Run
To run this sample code using Maven
>mvn jetty:run
Image may be NSFW.
Clik here to view.
Source Code @ GitHub