Tuesday, 23 February 2016

struts2: video upload example

In this post, I am going to explain how to upload a video file using struts2 framework. Struts2 provides fileUpload interceptor to upload files. By default it is part of default interceptor stack. fileUpload interceptor stack provides following parameters, by using these you can control the size of the file to upload, types of files to upload.

Property
Description
maximumSize
the maximum size in bytes. Default size is 2MB.
allowedTypes
a comma separated list of content types, image/png,image/gif,image/jpeg,application/pdf.
allowedExtensions
a comma separated list of file extensions (ie: .html) that the interceptor will allow a file reference to be set on the action. If none is specified allow all extensions to be uploaded.


Example
<action name="doUpload" class="com.sample.UploadAction">
 <interceptor-ref name="fileUpload">
  <param name="allowedTypes">video/x-ms-wmv,video/x-ms-avi,
   video/fli,video/x-fli,video/x-atomic3d-feature,video/gl,video/x-gl,video/x-isvideo,video/mpeg,video/x-motion-jpeg,video/quicktime,video/x-sgi-movie,
   video/x-mpeg,video/vnd.rn-realvideo,video/x-scm,video/mp4</param>
  <param name="maximumSize">1073741824</param>
 </interceptor-ref>
 <interceptor-ref name="validation">
  <param name="excludeMethods">input,back,cancel,browse</param>
 </interceptor-ref>
 <interceptor-ref name="workflow">
  <param name="excludeMethods">input,back,cancel,browse</param>
 </interceptor-ref>
 <interceptor-ref name="basicStack"/>
 <result name="success">/success.jsp</result>
 <result name="input">/index.jsp</result>
</action>

Following table summarizes the files; I am going to use to develop working application.
File
Description
UploadAction.java
Upload a file, return “success” on successful upload of file.
success.jsp
You will get this page once the file is uploaded successfully
index.jsp
HTML form to upload a file.

Following step-by-step procedure explains how to develop complete working application in Eclipse.
        
Step 1: Create new dynamic web project struts2_video_file_upload, in eclipse.
File -> New -> Dynamic Web project.

Step 2: Mavenize the project. Right click on the project -> Configure -> Conver to Maven Project.

Step 3 : Update pom.xml for maven dependencies. I am going to use following dependencies.

pom.xml
<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>struts2_video_file_upload</groupId>
 <artifactId>struts2_video_file_upload</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <build>
  <sourceDirectory>src</sourceDirectory>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.4</version>
    <configuration>
     <warSourceDirectory>WebContent</warSourceDirectory>
     <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
   </plugin>
  </plugins>
 </build>

 <dependencies>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts2-core</artifactId>
   <version>2.3.20</version>
  </dependency>

  <dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-io</artifactId>
   <version>1.3.2</version>
  </dependency>
 </dependencies>
</project>


Step 4: Update web.xml like below.
web.xml
<?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" 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>zimply</display-name>
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 <session-config>
  <session-timeout>1</session-timeout>
 </session-config>
</web-app>


Step 5: Create index.jsp and add following content.
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>file upload page</title>
</head>
<body>
 <h3>Struts 2 file upload example</h3>
 <s:form action="doUpload" method="post" enctype="multipart/form-data">
  <s:file name="document" label="Select the file to upload" />
  <s:submit value="upload" align="center" />
 </s:form>
</body>
</html>


Step 6: Define success.jsp like below.
success.jsp    
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>Upload Successful</title>
<s:head />
</head>
<body>

 <h3>File Uploaded successfully</h3>
 File Name :
 <s:property value="documentFileName"></s:property>
 <br /> Content type:
 <s:property value="documentContentType"></s:property>
 <br /> User file :
 <s:property value="document"></s:property>
</body>
</html>


Step 7: Create package com.sample, define UploadAction.java like below.

UploadAction.java
package com.sample;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;

import com.opensymphony.xwork2.ActionSupport;

public class UploadAction extends ActionSupport {
 private File document;
 private String documentFileName;
 private String documentContentType;

 public String execute() {
  String targetPath = "/Users/harikrishna_gurram/temp";
  File fileToCreate = new File(targetPath, documentFileName);
  try {
   FileUtils.copyFile(this.document, fileToCreate);
  } catch (IOException e) {
   addActionError(e.getMessage());
  }
  return "success";
 }

 public File getDocument() {
  return document;
 }

 public void setDocument(File document) {
  this.document = document;
 }

 public String getDocumentFileName() {
  return documentFileName;
 }

 public void setDocumentFileName(String documentFileName) {
  this.documentFileName = documentFileName;
 }

 public String getDocumentContentType() {
  return documentContentType;
 }

 public void setDocumentContentType(String documentContentType) {
  this.documentContentType = documentContentType;
 }

}


fileUpload automatically set the request parameters documentFileName, documentContentType based on the document. Suppose [File Name] is the actual file, then [File Name]ContentType represent the content type of the file, [File Name]FileName represent the actual name of the file uploaded.

Step 8: It is time to create struts.xml. Since Struts 2 requires struts.xml to be present in classes folder. Create struts.xml file under the WebContent/WEB-INF/classes folder. Eclipse does not create the "classes" folder by default, so you need to do this yourself. To do this, right click on the WEB-INF folder in the project explorer and select New > Folder. Create struts.xml file inside classes.

struts.xml
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
 <constant name="struts.multipart.maxSize" value="1073741824" />
 <package name="default" extends="struts-default">

  <action name="doUpload" class="com.sample.UploadAction">
   <interceptor-ref name="fileUpload">
    <param name="allowedTypes">video/x-ms-wmv,video/x-ms-avi,
     video/fli,video/x-fli,video/x-atomic3d-feature,video/gl,video/x-gl,video/x-isvideo,video/mpeg,video/x-motion-jpeg,video/quicktime,video/x-sgi-movie,
     video/x-mpeg,video/vnd.rn-realvideo,video/x-scm,video/mp4</param>
    <param name="maximumSize">1073741824</param>
   </interceptor-ref>
   <interceptor-ref name="validation">
    <param name="excludeMethods">input,back,cancel,browse</param>
   </interceptor-ref>
   <interceptor-ref name="workflow">
    <param name="excludeMethods">input,back,cancel,browse</param>
   </interceptor-ref>
   <interceptor-ref name="basicStack"/>
   <result name="success">/success.jsp</result>
   <result name="input">/index.jsp</result>
  </action>

 </package>

</struts>


There are two separate file size limits. First is struts.multipart.maxSize which comes from the Struts 2 default.properties file. This setting exists for security reasons to prohibit a malicious user from uploading extremely large files to file up your servers disk space. This setting defaults to approximately 2 megabytes and should be adjusted to the maximum size file (2 gigs max) that your will need the framework to receive. If you are uploading more than one file on a form the struts.multipart.maxSize applies to the combined total, not the individual file sizes. The other setting, maximumSize, is an interceptor setting that is used to ensure a particular Action does not receive a file that is too large.

Observe struts.xml, I set maximumSize to 1GB (1073741824 bytes). If user tries to upload any file > 1GB (or) invalid format, struts2 return index.jsp page by setting field errors.

Field errors are set by field interceptor automatically.
This interceptor will add several field errors, assuming that the action implements ValidationAware. These error messages are based on several i18n values stored in struts-messages.properties, a default i18n file processed for all i18n requests. You can override the text of these messages by providing text for the following keys:

Key
Description
struts.messages.error.uploading
A general error that occurs when the file could not be uploaded
struts.messages.error.file.too.large
occurs when the uploaded file is too large
struts.messages.error.content.type.not.allowed
occurs when the uploaded file does not match the expected content types specified
struts.messages.error.file.extension.not.allowed
occurs when the uploaded file does not match the expected file extensions specified

Complete project structure looks like below.
Run the application on server, You will get following screen.


References











Previous                                                 Next                                                 Home

5 comments:

  1. It work, Thanks. But how to set uploaded file's directory?

    ReplyDelete
    Replies
    1. Hi, it is my fault. The code could totally designate the directory. Thank you again. Have a nice day!

      Delete
  2. How to set size more than 2 mb for video file in struts.xml

    ReplyDelete
    Replies
    1. You can set file size using fileUpload interceptor. Refer struts.xml in this example

      Delete
  3. This comment has been removed by the author.

    ReplyDelete