This tutorial will demonstrate how to integrate DropzoneJS with Spring MVC. I'll cover in detail starting from creating a simple Spring MVC project, uploading files using DropzonJS and saving them in the server side, storing the files information in the database, downloading the files. The technologies used:
- Spring MVC 4.0.3 as a web framework
- Maven 3.1.1 as a build tool and for dependency management
- Hibernate 4.2.7.Final as an ORM tool
- Tomcat 7 as a web server
Let's get started and have some fun using DropzoneJS.
Objective:
The primary goal is to depict how to upload files using DropzoneJS. I'll also touch some of the customizing features. We'll then store the uploaded files information into database. We'll also see how to download those files.
Snapshots:
If you're curious to know what it will look like at the end, the following pictures are for you. For the image files, DropzoneJS displays a nice preview too.
1. Home Screen
2. Dragging the file over the region to attach
3. Listing out the attached files
4. Uploading completed
Project Setup
Now, add the following pom.xml right under the root springmvc-dropzonejs directory.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>np.com.mshrestha</groupId>
<artifactId>springmvc-dropzonejs</artifactId>
<name>photo-gallery</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<spring-version>4.0.3.RELEASE</spring-version>
<hibernate-version>4.2.7.Final</hibernate-version>
<hibernate-version>4.2.7.Final</hibernate-version>
<mysql-version>5.1.27</mysql-version>
<apache-connection-pooling-version>1.4</apache-connection-pooling-version>
</properties>
<dependencies>
<!-- Spring
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-version}</version>
</dependency>
<!-- Servlet
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Apache
Commons FileUpload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Common IO
-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<!-- Jackson JSON Processor
-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate-version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate-version}</version>
</dependency>
<!-- Apache's
Database Connection Pooling -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${apache-connection-pooling-version}</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>${apache-connection-pooling-version}</version>
</dependency>
<!-- MySQL
-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Tomcat
7 plugin -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
</plugins>
</build>
</project>Now, open the command prompt, go to the root directory and then type mvn eclipse:eclipse. This will generate the Eclipse configuration files so that eclipse recognizes the root directory as a project directory. For instance, you'll see the files
.classpath
, .project
created under the root directory.
The above
pom.xml
contains dependencies for Spring, Servlet, Apache File I/O and Jackson JSON processor. You can also see the Tomcat 7 plugin.Now, we're ready to import the project in eclipse. You can import the project either as 'General -> Existing Projects into Workspace' or as 'Maven -> Existing Maven Projects'.
Let's create the following java source packages under the 'src/java/main' directory.
- np.com.mshrestha.dropzonetest.model
- np.com.mshrestha.dropzonetest.dao
- np.com.mshrestha.dropzonetest.dao.impl
- np.com.mshrestha.dropzonetest.service
- np.com.mshrestha.dropzonetest.service.impl
- np.com.mshrestha.dropzonetest.controller
Please note that just to upload the files to server, we don't need any model classes, daos, services. Only controller is sufficient for that. Having said that, in this example we're going to store the uploaded file information in the database so that we can retrieve back the information.
Deployment Descriptor: web.xml
webapp
directory and add the deployment descriptor web.xml
under WEB-INF. The web.xml defines root spring container and the heart of the spring MVC - 'DispatcherServlet
'.web.xml ( path: /webapp/WEB-INF/web.xml )
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app.xsd">
<!-- The definition of the Root Spring Container shared by
all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<!-- Creates the
Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Processes
application requests -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
The above web.xml simply defines the dispatcher servlet and the two configuration xmls. I intentionally created those two config xmls to let you know that we can initialize parameters in two ways. This will be needed if you have multiple servlets and filters that shares common parameters. You can define only one servlet config xml and put all of contents from both xmls into the one. The tag <context-param> defines parameters that are shared by all servlets and filters whereas <init-param> defines parameters that are accessible by only that <servlet> inside which it is placed. We also defined the DispatcherServlet which is the default request handler for all the requests as defined by the pattern "/" in <url-pattern>.
Let's create the two context configuration files alongside web.xml under the WEB-INF directory.
servlet-context.xml ( path: /webapp/WEB-INF/servlet-context.xml )
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
default-lazy-init="true">
<!--
DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the
Spring MVC @Controller programming model -->
<annotation-driven />
<context:component-scan base-package="np.com.mshrestha.dropzonetest.controller"
/>
<!-- Defines a
resolver implementation bean. It gets applied to all requests handled by that
DispatcherServlet -->
<beans:bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
/>
<!-- Handles
HTTP GET requests for /web-resources/** by efficiently serving up static
resources in the ${webappRoot}/resources/ directory -->
<resources mapping="/web-resources/**"
location="/resources/" />
<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<beans:property name="useTrailingSlashMatch"
value="true" />
</beans:bean>
<!-- Resolves
views selected for rendering by @Controllers to .jsp resources in the
/WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix"
value="/WEB-INF/views/" />
<beans:property name="suffix"
value=".jsp" />
</beans:bean>
</beans:beans>In the above, it sets the property useTrailingSlashMatch of the bean RequestMappingHandlerMapping true. This is to match to URLs irrespective of the presence of a trailing slash. When it's true, the controller method mapped to "/listFiles" also matches to "/listFiles/".
Also, it defines the CommonsMultipartResolver bean, an implementation class of MultipartResolver.
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
We needed to define it explicitly because there is no default resolver implementation used for Spring DispatcherServlets, as an application might choose to parse its multipart requests itself. To define an implementation, create a bean with the id "multipartResolver" in a DispatcherServlet's application context. Such a resolver gets applied to all requests handled by that DispatcherServlet.root-context.xml ( path: /webapp/WEB-INF/root-context.xml )
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Root
Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="np.com.mshrestha.dropzonetest"
/>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource"
ref="dataSource" />
<property name="packagesToScan">
<list>
<value>np.com.mshrestha.dropzonetest.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory"
ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"
/>
</beans>
The above root-context.xml looks pretty straight-forward. The database property file looks like as follows:
database.properties ( path: /src/main/resources/database.properties )
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/dropzone_test?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;autoReconnect=true
jdbc.username=root
jdbc.password=root
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
Persistence
UploadedFile
under the package np.com.mshrestha.dropzonetest.model
. The class corresponds to the table uploaded_file.UploadedFile.java
package np.com.mshrestha.dropzonetest.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "uploaded_file")
public class UploadedFile {
private Long id;
private String name;
private String location;
private Long size;
private String type;
@Id
@GeneratedValue(strategy =
GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(nullable = false)
public String getName() {
return name;
}
@Column(nullable = false)
public String getLocation()
{
return location;
}
@Column()
public Long getSize() {
return size;
}
@Column(nullable = false)
public String getType() {
return type;
}
// setter methods...
}
Note that we don't store the file itself in the database. Instead, we only store its name and location.
Dao Layer
FileUploadDao.java
package np.com.mshrestha.dropzonetest.dao;
import java.util.List;
import np.com.mshrestha.dropzonetest.model.UploadedFile;
public interface FileUploadDao {
List<UploadedFile> listFiles();
UploadedFile getFile(Long id);
UploadedFile saveFile(UploadedFile
uploadedFile);
}
FileUploadDaoImpl.java
package np.com.mshrestha.dropzonetest.dao.impl;
import java.util.List;
import np.com.mshrestha.dropzonetest.dao.FileUploadDao;
import np.com.mshrestha.dropzonetest.model.UploadedFile;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class FileUploadDaoImpl implements FileUploadDao {
@Autowired
private SessionFactory sessionFactory;
public List<UploadedFile>
listFiles() {
return getSession().createCriteria(UploadedFile.class).list();
}
public UploadedFile getFile(Long id) {
return (UploadedFile)
getSession().get(UploadedFile.class, id);
}
public UploadedFile saveFile(UploadedFile
uploadedFile) {
return (UploadedFile)
getSession().merge(uploadedFile);
}
private Session getSession() {
Session sess = getSessionFactory().getCurrentSession();
if (sess == null) {
sess = getSessionFactory().openSession();
}
return sess;
}
private SessionFactory
getSessionFactory() {
return sessionFactory;
}
}
Service Layer
FileUploadService.java
package np.com.mshrestha.dropzonetest.service;
import java.util.List;
import np.com.mshrestha.dropzonetest.model.UploadedFile;
public interface FileUploadService {
List<UploadedFile> listFiles();
UploadedFile getFile(Long id);
UploadedFile saveFile(UploadedFile uploadedFile);
}
FileUploadServiceImpl.java
package np.com.mshrestha.dropzonetest.service.impl;
import java.util.List;
import np.com.mshrestha.dropzonetest.dao.FileUploadDao;
import np.com.mshrestha.dropzonetest.model.UploadedFile;
import np.com.mshrestha.dropzonetest.service.FileUploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class FileUploadServiceImpl implements FileUploadService {
@Autowired
private FileUploadDao dao;
@Transactional(readOnly = true)
public
List<UploadedFile> listFiles() {
return dao.listFiles();
}
@Transactional(readOnly = true)
public UploadedFile
getFile(Long id) {
return dao.getFile(id);
}
@Transactional
public UploadedFile
saveFile(UploadedFile uploadedFile) {
return dao.saveFile(uploadedFile);
}
}
So far, we've dealt everything needed for Service layer and DAO layer. I'm assuming you have no problem understanding the usage of the various annotations. Now, let's take a look into the Web Layer.
Presentation ( Web ) Layer
Controller
Now we're going to create a controller that handles all the requests from the DispatcherServlet. Let's create the controller FileUploadController under the package np.com.mshrestha.dropzonetest.controller.
FileUploadController.java
package np.com.mshrestha.dropzonetest.controller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import np.com.mshrestha.dropzonetest.model.UploadedFile;
import np.com.mshrestha.dropzonetest.service.FileUploadService;
import org.apache.commons.io.FileUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import
org.springframework.web.multipart.MultipartHttpServletRequest;
@Controller
public class FileUploadController {
@Autowired
private FileUploadService
uploadService;
@RequestMapping("/")
public String home() {
// will be resolved to /views/fileUploader.jsp
return "fileUploader";
}
@RequestMapping(value
= "/upload", method =
RequestMethod.POST)
public @ResponseBody
List<UploadedFile>
upload(MultipartHttpServletRequest request,
HttpServletResponse
response) throws IOException {
// Getting uploaded
files from the request object
Map<String,
MultipartFile> fileMap = request.getFileMap();
// Maintain a list
to send back the files info. to the client side
List<UploadedFile>
uploadedFiles = new ArrayList<UploadedFile>();
// Iterate through
the map
for (MultipartFile
multipartFile : fileMap.values()) {
// Save the file to
local disk
saveFileToLocalDisk(multipartFile);
UploadedFile
fileInfo = getUploadedFileInfo(multipartFile);
// Save the file
info to database
fileInfo
= saveFileToDatabase(fileInfo);
// adding the file
info to the list
uploadedFiles.add(fileInfo);
}
return uploadedFiles;
}
@RequestMapping(value
= { "/list" })
public String
listBooks(Map<String, Object> map) {
map.put("fileList",
uploadService.listFiles());
// will be resolved to /views/listFiles.jsp
return "/listFiles";
}
@RequestMapping(value
= "/get/{fileId}", method =
RequestMethod.GET)
public void
getFile(HttpServletResponse response, @PathVariable Long fileId) {
UploadedFile
dataFile = uploadService.getFile(fileId);
File file = new
File(dataFile.getLocation(), dataFile.getName());
try {
response.setContentType(dataFile.getType());
response.setHeader("Content-disposition", "attachment;
filename=\""
+
dataFile.getName() + "\"");
FileCopyUtils.copy(FileUtils.readFileToByteArray(file),
response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
private void
saveFileToLocalDisk(MultipartFile multipartFile)
throws IOException,
FileNotFoundException {
String
outputFileName = getOutputFilename(multipartFile);
FileCopyUtils.copy(multipartFile.getBytes(),
new FileOutputStream(
outputFileName));
}
private UploadedFile
saveFileToDatabase(UploadedFile uploadedFile) {
return
uploadService.saveFile(uploadedFile);
}
private String
getOutputFilename(MultipartFile multipartFile) {
return
getDestinationLocation() + multipartFile.getOriginalFilename();
}
private UploadedFile
getUploadedFileInfo(MultipartFile multipartFile)
throws IOException {
UploadedFile
fileInfo = new UploadedFile();
fileInfo.setName(multipartFile.getOriginalFilename());
fileInfo.setSize(multipartFile.getSize());
fileInfo.setType(multipartFile.getContentType());
fileInfo.setLocation(getDestinationLocation());
return fileInfo;
}
private String
getDestinationLocation() {
return "D:/uploaded-files/";
}
}upload(): This method is called when the files are uploaded to server. The method is pretty simple and understandable. Otherwise, the comments will help you to understand. As you can see, the method parameters are little different than the usual controller methods. The interface MultipartHttpServletRequest
extends HttpServletRequest and MultipartRequest. It provides additional methods for dealing with multipart content within a servlet request, allowing to access uploaded files. And it's implementation comes from the MultipartResolver bean called CommonsMultipartResolver that we defined in servlet-context.xml.
getFile(): The method returns the requested file in the downloadable format. Note that we need to add the header 'Content-disposition' to the response to make the file downloadable.
The rest of the methods should be effortless to understand.
JSPs
We're going to create two JSP pages, one, the homepage, for uploading the files while another is for viewing all the uploaded files in the servers which will have download option too.
fileUploader.jsp ( path: /webapp/WEB-INF/views/fileUploader.jsp )
<%@
taglib uri="http://java.sun.com/jsp/jstl/core"
prefix="c"%>
<!DOCTYPE
html>
<html>
<head>
<meta charset="utf-8" name="viewport"
content="width=device-width,
initial-scale=1">
<title>Spring MVC + Dropzone.js Example</title>
<link rel="stylesheet" type="text/css"
href='<c:url value="/web-resources/libs/bootstrap-3.1.1/css/bootstrap.min.css"/>'>
<link rel="stylesheet" type="text/css"
href='<c:url value="/web-resources/libs/bootstrap-dialog/css/bootstrap-dialog.min.css"/>'>
<link rel="stylesheet" type="text/css"
href='<c:url value="/web-resources/css/style.css"/>'>
</head>
<body>
<div class="container">
<div class="panel
panel-default">
<div class="panel-heading
text-center">
<h3>Spring MVC +
Dropzone.js Example</h3>
</div>
<div class="panel-body">
<div>
<form id="dropzone-form"
class="dropzone"
enctype="multipart/form-data">
<div class="dz-default dz-message file-dropzone text-center
well col-sm-12">
<span class="glyphicon
glyphicon-paperclip"></span> <span>
To
attach files, drag and drop here</span><br>
<span>OR</span><br>
<span>OR</span><br>
<span>Just Click</span>
</div>
<!-- this is
were the previews should be shown. -->
<div class="dropzone-previews"></div>
</form>
<hr>
<button id="upload-button"
class="btn btn-primary">
<span class="glyphicon
glyphicon-upload"></span> Upload
</button>
<a class="btn
btn-primary pull-right" href="list"> <span
class="glyphicon glyphicon-eye-open"></span> View All Uploads
</a>
</div>
</div>
</div>
</div>
<script type="text/javascript"
src='<c:url value="/web-resources/libs/jquery/jquery-2.1.1.js"/>'></script>
<script type="text/javascript"
src='<c:url value="/web-resources/libs/bootstrap-3.1.1/js/bootstrap.js"/>'></script>
<script type="text/javascript"
src='<c:url value="/web-resources/libs/bootstrap-dialog/js/bootstrap-dialog.min.js"/>'></script>
<script type="text/javascript"
src='<c:url value="/web-resources/libs/dropzone.js"/>'></script>
<script type="text/javascript"
src='<c:url value="/web-resources/js/app.js"/>'></script>
</body>
</html>
It's quite easy to integrate DropzoneJS. It starts with the <form> tag with class="dropzone". That's pretty much of it. Dropzone will find all form elements with the class dropzone, automatically attach itself to it, and upload files dropped into it to the specified action attribute. The only additional thing to do is to initialize the Dropzone configuration. The configuration is stored under the
Dropzone.options
object. It looks something like this:
Dropzone.options.dropzoneForm = {
url : "/form/action/url",
autoProcessQueue
: false,
uploadMultiple
: true,
maxFilesize
: 256, //
MB
previewsContainer : ".dropzone-previews",
previewsContainer : ".dropzone-previews",
init : function() {
// handling events
}
}
I've configured that in a separate JS file which we'll see in few minutes later. That's all we have to do for setting up DropzoneJS. Isn't that cool?
For each uploading file, Dropzone generates some HTML elements with dropzone classes. This is to display the file specific information like file name, file size, image preview, upload progress, success indicator, error indicator, error messages. And the best part here is they are easily customizable. The generated HTML is as follows:
<div class="dz-preview
dz-file-preview">
<div class="dz-details">
<div class="dz-filename">
<span data-dz-name></span>
</div>
<div class="dz-size"
data-dz-size></div>
<img data-dz-thumbnail
/>
</div>
<div class="dz-progress">
<span class="dz-upload"
data-dz-uploadprogress></span>
</div>
<div class="dz-success-mark">
<span>✔</span>
</div>
<div class="dz-error-mark">
<span>✘</span>
</div>
<div class="dz-error-message">
<span data-dz-errormessage></span>
</div>
</div>
We can access the HTML of the file preview in any of the events with
file.previewElement
.Dropzone also creates a <div> element with class="dz-default dz-message" with default message "Drop files to upload (or click)". As depicted in the above JSP page, we can override the default message by putting the <div> element with class="dz-message" inside the dropzone form. This <div> element is the actual drop zone where we can drop the files or simply click to open the file chooser dialog.
Also, I've added an effect such that if a file is dragged over the message <div>, it outlines the <div> so that we can know the file is over the correct region to drop.
Also, we've created an empty <div> element with class="dropzone-previews". I've configured this div in the dropzone configuration as a container for all the dropzone generated preview elements. This is done by adding previewsContainer : ".dropzone-previews" in the dropzone configuration.
Moreover, I've customized the default progress bar too. In the dropzone configuration, the progress bar has been customized to show the progress percentage. It is done inside dropzone's uploadprogress event.
The following is the JS file I created and placed it under the '/webapp/resources/js/' directory.
app.jsp ( path: /webapp/resources/js/app.js )
$(document).ready(function() {
$(".file-dropzone").on('dragover', handleDragEnter);
$(".file-dropzone").on('dragleave', handleDragLeave);
$(".file-dropzone").on('drop', handleDragLeave);
function handleDragEnter(e) {
this.classList.add('drag-over');
}
function handleDragLeave(e) {
this.classList.remove('drag-over');
}
//
"dropzoneForm" is the camel-case version of the form id "dropzone-form"
Dropzone.options.dropzoneForm
= {
url : "upload", // not required if the <form> element has action attribute
autoProcessQueue
: false,
uploadMultiple
: true,
maxFilesize :
256, //
MB
parallelUploads
: 100,
maxFiles : 100,
addRemoveLinks
: true,
previewsContainer
: ".dropzone-previews",
// The setting up
of the dropzone
init : function() {
var myDropzone = this;
// first set
autoProcessQueue = false
$('#upload-button').on("click", function(e) {
myDropzone.processQueue();
});
// customizing the default progress bar
this.on("uploadprogress", function(file, progress) {
progress
= parseFloat(progress).toFixed(0);
var progressBar =
file.previewElement.getElementsByClassName("dz-upload")[0];
progressBar.innerHTML
= progress + "%";
});
// displaying the uploaded files information in a Bootstrap dialog
this.on("successmultiple", function(files,
serverResponse) {
showInformationDialog(files,
serverResponse);
});
}
}
function showInformationDialog(files,
objectArray) {
var responseContent = "";
for (var i = 0; i <
objectArray.length; i++) {
var infoObject =
objectArray[i];
for ( var infoKey in infoObject) {
if
(infoObject.hasOwnProperty(infoKey)) {
responseContent
= responseContent + " " + infoKey + " -> " +
infoObject[infoKey] + "<br>";
}
}
responseContent
= responseContent + "<hr>";
}
// from the library bootstrap-dialog.min.js
BootstrapDialog.show({
title : '<b>Server
Response</b>',
message
: responseContent
});
}
That's all I have for the dropzone integration. The only remaining part for this tutorial is to see another page that lists out all the uploaded files in the server. The page will have a download button for each file listed. Let's have a look.
listFiles.jsp ( path: /webapp/WEB-INF/views/listFiles.jsp )
<%@
taglib uri="http://java.sun.com/jsp/jstl/core"
prefix="c"%>
<!DOCTYPE
html>
<html>
<head>
<meta charset="utf-8" name="viewport"
content="width=device-width,
initial-scale=1">
<title>Spring MVC + Dropzone.js Example</title>
<link rel="stylesheet" type="text/css"
href='<c:url value="/web-resources/libs/bootstrap-3.1.1/css/bootstrap.min.css"/>'>
<link rel="stylesheet" type="text/css"
href='<c:url value="/web-resources/libs/bootstrap-dialog/css/bootstrap-dialog.min.css"/>'>
<link rel="stylesheet" type="text/css"
href='<c:url value="/web-resources/css/style.css"/>'>
</head>
<body>
<div class="container">
<div class="panel
panel-default">
<div class="panel-heading
text-center">
<h3>Spring MVC +
Dropzone.js Example</h3>
</div>
<div class="panel-body">
<a class="btn
btn-primary" href="${pageContext.request.contextPath}">
<span class="glyphicon
glyphicon-chevron-left"></span> Go Back
</a>
<br>
<h4>List of All Uploaded
Files</h4>
</div>
<table class="table
table-hover table-condensed">
<thead>
<tr>
<th width="5%">S.N</th>
<th width="40%">File Name</th>
<th width="20%">File Type</th>
<th width="15%">File Size</th>
<th width="10%">Actions</th>
</tr>
</thead>
<tbody>
<c:forEach items="${fileList}"
var="dataFile" varStatus="loopCounter">
<tr>
<td><c:out value="${loopCounter.count}"
/></td>
<td><c:out value="${dataFile.name}"
/></td>
<td><c:out value="${dataFile.type}"
/></td>
<td><c:out value="${dataFile.size}"</td>
<td>
<a class="btn
btn-primary" href="${pageContext.request.contextPath}/get/${dataFile.id}">
<span class="glyphicon
glyphicon-download"></span> Download
</a>
</td>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
<script type="text/javascript"
src='<c:url value="/web-resources/libs/jquery/jquery-2.1.1.js"/>'>
</script>
<script type="text/javascript"
src='<c:url value="/web-resources/libs/bootstrap-3.1.1/js/bootstrap.js"/>'>
</script>
</body>
</html>
Download
Running the application
Now, running the application is quite simple enough.
Now, running the application is quite simple enough.
- Open the Command Prompt
- Go to the root project directory ( springmvc-dropzonejs )
- Run the mvn command to download all dependent JARs.
- Type mvn and hit <Enter>.
- Run Tomcat server
- mvn tomcat7:run
- Go to the browser and enter the following URL:
- http://localhost:8080/springmvc-dropzonejs/
- The port number might be different in your case. Please have a look at the tomcat log in console for that.
Questions???
Feel free to shoot me an email or comment below if you have any questions or confusions.
How to run this project in eclipse?
ReplyDeleteHello Shaunak,
DeleteFor running the project in eclipse, please follow the steps below ( I'm assuming you've already imported the project in eclipse):
1. Right click on the project -> Run As -> Run Configurations...
2. On the left side of the dialog, you'll see 'Maven Build'. Double click it to create a new maven build configuration.
3. The configuration name is defaulted to 'New_configuration' at the top. You can rename it whatever you like.
4. For the 'Base Directory:', click on the 'Browse Workspace...' button and select the project.
5. Now, in the 'Goals...' section, put 'eclipse:clean eclipse:clean tomcat7:run'
6. Then, Apply and Run. You can see the logs in eclipse console.
7. Once the tomcat has started, go to a browser and enter the url.
8. That's it.
I hope this helps.
Thanks.
I am getting an exception
DeleteI can see the view but file is not fetting uploaded....
here follows the exception:
https://docs.google.com/document/d/1dEVIlBHXTW-k5MDEd6KCTXaoGAdUrq1AV8AweT9CsHI/edit?usp=sharing
Deletethis is the, link...pl...look at it
Here i think problem is with database access.
DeleteI don't know hibernate, i m only familiar with spring and jsp and JS.
Please do help me with database connectivity and storing part.
Awaiting for you reply...
Yes, as you said, the problem is due to connection failure with the database. In the 'database.properties' file, I've set both username and password as 'root'. Could you check your database login credentials and update the file accordingly? Let me know if that works or not.
DeleteThank you so much bro...
DeleteIts perfectly working fine...
Just one more favour...
can u guide me how to deploy it on the server?
means i have my own server and a website hosted on it.
I want to put this app there, can you guide me fr it?
Is there any solution to limit the number of files dropped at a time?
DeleteI want to allow only one file dropped at a time.
can you reply to my last message please...???
DeleteI want to knw that how we can restrict no. of file while dropping?
please...help me!
Thank you!
You can check the no. of files in drag & drop event handlers, perform any custom logic as per required.
DeleteFor example, if only one file should be allowed to drop at a time, you can do something as follows:
========================================================
$(".file-dropzone").on('drop', handleDragDrop);
function handleDragDrop(e) {
var files = e.originalEvent.dataTransfer.files;
if ( files.length > 1) {
alert( "Can't drag and drop more than one file at a time...");
e.stopPropagation();
e.preventDefault();
}
}
Manoj Shrestha'S Blog: Dropzone Js + Spring Mvc + Hibernate Integration (Complete Example) >>>>> Download Now
Delete>>>>> Download Full
Manoj Shrestha'S Blog: Dropzone Js + Spring Mvc + Hibernate Integration (Complete Example) >>>>> Download LINK
>>>>> Download Now
Manoj Shrestha'S Blog: Dropzone Js + Spring Mvc + Hibernate Integration (Complete Example) >>>>> Download Full
>>>>> Download LINK 9e
Hello Manoj,
ReplyDeleteBest tuto!! thanks
But, how do we can easly integrate DropeZone into an existing form with other fields like: name, email...
Thanks in advance for your answer,
Ismail
Hello Ismail,
ReplyDeleteSince, MultipartHttpServletRequest extends HttpServletRequest, the form fields like name, email etc. also come along as request parameters. You might already know, we can check the request parameters like this:
Enumeration params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = params.nextElement();
System.out.println("Param: " + param);
System.out.println("Value: " + request.getParameter(param));
}
---
So, if the form field name is "email", you can access the input value using:
String email = request.getParameter("email");
---
I hope this helps.
Hello,
ReplyDeleteThanks again for your quick answer, getting form info is working fine using getParameter method...
Otherwise, How do you use return value uploadedFiles of upload method on client side? is there a hiden generated JSTL ( or Java code ) code allowing the use of uploadedFiles object?
Thanks.
Ismail
I am asking about return value uploadedFiles management as i need it to perform a validation of the values of my form ( name, email...etc )before putting them into database.
ReplyDeleteTahnks.
Ismail
If you need to have client side validation, why do you need uploadedFiles from server??? You should validate the form on client side before the form submission. Am I missing anything here?
DeleteYes sure, i can do it using JavaScript on client side, but i prefer do it on server side in Java to avoid all issues
Deletelinked to Javascript deactivation by user, so we will have alawys a good working of the application in such case...
How can i do it using JSPs you provided in this tutorial?
Thanks for your help,
Ismail
THANK YOU SO MUCH, THIS WAS AN AMAZING TUTORIAL.... RUN AT THE FIRST TRIAL... READY TO INTEGRATED TO MY WEB SITE... SIMPLY AMAZING..
ReplyDeleteHello Manoj,
ReplyDeleteDo you know how to submit dropezone form with 0 files to upload?
My form is including dropzone + other fields; name, email ...so i would like to make optional uploading files...
Thanks in advance for your help.
Ismail
DropzoneJS's processQueue() method does not submit the form if there is no upload file. One solution could be to perform usual form submission. Inside the upload button click handler, you can check the uploading files size. If there's at least one uploading file, use DropzonJS's processQueue() othewise use Form.submit(). For instance:
Delete---------
var noOfQueuedFiles = myDropzone.getQueuedFiles().length;
if (noOfQueuedFiles > 0)
myDropzone.processQueue();
else
$("#dropzone-form").submit();
------
And one last thing, don't forget to add "action" and "method" attributes in the < form > element.
Hope this helps.
Hello,
DeleteI tryied with this, there is no request received by the controller "/upload".
So i have used another way to fix this issue => send a empty list of files when there is no file added into dropzone form:
app.js:
$('input[type="submit"]').on("click", function (e) {
if (myDropzone.getQueuedFiles().length > 0){
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
}else{
e.preventDefault();
e.stopPropagation();
myDropzone.uploadFiles([]); //send empty
}
});
It is working fine!!!! but i have another issue now, the validation of my form using JQuerry validator is not working.
in my JSP:
....
After form description i added this: ( all needed JS librairies have been included of course)
$.validate(); => Validation does not work.
Please have a look at this issue.
Thanks,
Ismail
On the other hand, How can i send object from /upload controller to UploadFile.JSP,
DeleteI need it to display errors on form in case email, name..validation failed!
Thanks
Hi Thanks for visit us:
ReplyDeleteARKA Softwares & Outsourcing is an IT Company focusing on software & Web development and providing offshore outsourcing solutions to enterprises worldwide.website development company in usa
in the listFiles.jsp, all the jstl were ignored. Only after adding this line to the top if the file, it started working
ReplyDelete<%@ page isELIgnored="false"%>
Just in case someone has the same issue!
Hello Anand,
DeleteSounds like you're using old version of deployment descriptor, version 2.3 or older. The new version of descriptor, 2.4 or newer, evaluates EL expressions by default.
Thanks.
Nice sample...learn using maven w/elipse luna/1.8, spring+hibernate; jquery & bootstrap too...
ReplyDelete*updated pom.xml w/tomcat plugin to 2.2 & it worked:
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
man where is the script for the databse, thanks!
ReplyDeleteWe don't need any database scripts. Once you run the tomcat, it will create the database and the tables on it's own based on the annotations defined in the model classes.
Deletecan we upload the folder using dropzonejs
ReplyDeleteHi all,
ReplyDeleteI have completed this demo but i try to read file from server and display same add page, but i use code below but image big size and not well,
Can anyone help me to solve this problem Thanks you very much
$(document).ready(function(){
Dropzone.options.dropzoneForm = {
init: function() {
thisDropzone = this;
var mockFile = { name: 'rajkram_1.jpg', size: 123 };
thisDropzone.options.addedfile.call(thisDropzone, mockFile);
thisDropzone.options.thumbnail.call(thisDropzone, mockFile, '/TLG_v2/resources/golf_course/Rachakram/rajkram_1.jpg');
}
};
});
I just came by to tell you how much i appreciate you work.
ReplyDeleteRegards,
Branko
Hello Sir,
ReplyDeleteThank you for this awesome work. It helped me a lot. Please keep doing this great work.
I have one question : I don't want to upload my file to my local disk, I want to use an online storage database/server. How can I do that ?
Thank you
I thought this was a pretty interesting read when it comes to this topic. Thank you
ReplyDeleteNsasoft Office Product Key Finder Crack
MacBooster Crack
Dropzone Crack
Minitab Crack
Manoj Shrestha'S Blog: Dropzone Js + Spring Mvc + Hibernate Integration (Complete Example) >>>>> Download Now
ReplyDelete>>>>> Download Full
Manoj Shrestha'S Blog: Dropzone Js + Spring Mvc + Hibernate Integration (Complete Example) >>>>> Download LINK
>>>>> Download Now
Manoj Shrestha'S Blog: Dropzone Js + Spring Mvc + Hibernate Integration (Complete Example) >>>>> Download Full
>>>>> Download LINK
Being one of the leading Website Development companies in India, our expertise in custom website development covers most of your needs.
ReplyDeleteMuğla
ReplyDeleteSamsun
Eskişehir
Sakarya
Kars
NNBF
Mardin
ReplyDeleteistanbul
Çanakkale
Antep
Elazığ
LJ04H
https://titandijital.com.tr/
ReplyDeleteafyon parça eşya taşıma
düzce parça eşya taşıma
erzincan parça eşya taşıma
elazığ parça eşya taşıma
UA0
432C9
ReplyDeletetekirdağ ücretsiz görüntülü sohbet
erzincan canlı sohbet siteleri
en iyi ücretsiz sohbet uygulamaları
istanbul ücretsiz görüntülü sohbet uygulamaları
muş telefonda canlı sohbet
canlı sohbet bedava
malatya muhabbet sohbet
istanbul canlı sohbet ücretsiz
aydın görüntülü sohbet
4106C
ReplyDeleteşırnak rastgele görüntülü sohbet
şırnak sesli sohbet odası
malatya görüntülü sohbet ücretsiz
görüntülü sohbet siteleri
Kars Rastgele Sohbet
yozgat canlı görüntülü sohbet
canlı sohbet uygulamaları
giresun ücretsiz sohbet
van görüntülü sohbet siteleri ücretsiz
D9FBB
ReplyDeleteJns Coin Hangi Borsada
Hamster Coin Hangi Borsada
Bitcoin Çıkarma
Kripto Para Nasıl Kazılır
Nonolive Takipçi Satın Al
Linkedin Beğeni Hilesi
Baby Doge Coin Hangi Borsada
Bulut Madenciliği Nedir
Ort Coin Hangi Borsada
2776C
ReplyDeletesafepal
defillama
satoshi
bitbox
layerzero
solflare
poocoin
roninchain
arbitrum