1、新建动态web项目,并且转换为maven项目,方便项目管理,并且写一个简单的springmvc框架,这里参照文章:点击打开链接
2、进度以json格式返回,这里参考文章:点击打开链接
3、项目目录如下:
4、依次列出代码,CustomMultipartResolver.java:
package com.busymonkey;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
public class CustomMultipartResolver extends CommonsMultipartResolver {
@Autowired
private MyProgressListener progressListener;
public void setFileUploadProgressListener(MyProgressListener progressListener){
this.progressListener=progressListener;
}
@Override
public MultipartParsingResult parseRequest(HttpServletRequest request)
throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
progressListener.setSession(request.getSession());
fileUpload.setProgressListener(progressListener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
}
catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
}
catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
}
}
5、MyProgressListener.java:
package com.busymonkey;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.ProgressListener;
import org.springframework.stereotype.Component;
@Component
public class MyProgressListener implements ProgressListener {
private HttpSession session;
public void setSession(HttpSession session){
this.session=session;
ProgressEntity status = new ProgressEntity();
session.setAttribute("status", status);
}
/*
* pBytesRead 到目前为止读取文件的比特数 pContentLength 文件总大小 pItems 目前正在读取第几个文件
*/
public void update(long pBytesRead, long pContentLength, int pItems) {
ProgressEntity status = (ProgressEntity) session.getAttribute("status");
status.setpBytesRead(pBytesRead);
status.setpContentLength(pContentLength);
status.setpItems(pItems);
}
}
6、ProgressEntity.java:
package com.busymonkey;
public class ProgressEntity {
private long pBytesRead = 0L; //到目前为止读取文件的比特数
private long pContentLength = 0L; //文件总大小
private int pItems; //目前正在读取第几个文件
public long getpBytesRead() {
return pBytesRead;
}
public void setpBytesRead(long pBytesRead) {
this.pBytesRead = pBytesRead;
}
public long getpContentLength() {
return pContentLength;
}
public void setpContentLength(long pContentLength) {
this.pContentLength = pContentLength;
}
public int getpItems() {
return pItems;
}
public void setpItems(int pItems) {
this.pItems = pItems;
}
@Override
public String toString() {
float tmp = (float)pBytesRead;
float result = tmp/pContentLength*100;
return "ProgressEntity [pBytesRead=" + pBytesRead + ", pContentLength="
+ pContentLength + ", percentage=" + result + "% , pItems=" + pItems + "]";
}
}
7、StartController.java:
package com.busymonkey;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;
@Controller
@SessionAttributes("status")
public class StartController {
@RequestMapping("/hello")
public ModelAndView hello() {
String message = "Hello World, Spring 3.0!";
System.out.println(message);
return new ModelAndView("hello1", "message", message);
}
@RequestMapping("/upload")
public String upLoad(HttpServletRequest request, HttpServletResponse response)
throws IllegalStateException, IOException {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
if (multipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Iterator<String> iter = multiRequest.getFileNames();
while (iter.hasNext()) {
MultipartFile file = multiRequest.getFile((String) iter.next());
if (file != null) {
String fileName = file.getOriginalFilename();
String path = "D:/" + fileName;
File localFile = new File(path);
file.transferTo(localFile);
}
}
}
return "/hello1";
}
@RequestMapping(value = "/getProgress")
@ResponseBody
public String initCreateInfo(Map<String, Object> model) {
ProgressEntity status = (ProgressEntity) model.get("status");
if(status==null){
return "{}";
}
return status.toString();
}
}
如果进度查询改为 ProgressEntity status = (ProgressEntity) request.getSession().getAttribute("status");也是一样的效果
8、hello1.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<p>hello1</p>
</body>
</html>
9、spring-servlet.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: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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.busymonkey" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
<bean id="multipartResolver" class="com.busymonkey.CustomMultipartResolver">
<property name="maxUploadSize" value="3000000000"/>
<property name="maxInMemorySize" value="4096"/>
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
<mvc:annotation-driven />
</beans>
10、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_2_5.xsd">
<display-name>Spring3MVC</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
11、index.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Spring 3.0 MVC demo</title>
</head>
<body>
<a href="hello.html">Say Hello</a>
<h3>upload :</h3>
Please choose the file :<br />
<form action="upload.html" method="post" enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="Upload" />
</form>
<a href="getProgress.html">progress</a>
</body>
</html>
12、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>com</groupId>
<artifactId>busymonkey</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</project>
浏览器打开查询进度的页面可以单独获取到进度信息。
第二篇:
以上的文章是结合spring做的进度查询,虽然是实现了依赖注入,但是此方案不适用与多文件上传,即对于分别通过两个或以上的请求上传的文件,后一个进度查询请求会把之前的请求给覆盖,因为 ProgressListener 在其他地方被调用的时候很多地方使用的是static 以及一些是 final,所以在多线程时候会出问题,这里只能通过包闭函数的方式来处理此类问题,不过这也导致整个spring框架会有局部的非依赖注入,修改的代码如下,这里也不需要重写 ProgressListener 接口了,也不需要 ProgressEntity 实体类了:
CustomMultipartResolver.java:
package com.busymonkey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
public class CustomMultipartResolver extends CommonsMultipartResolver {
private static Map<String, String> progressMap = new HashMap<String, String>();
@Override
public MultipartParsingResult parseRequest(HttpServletRequest request)
throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
final String para = request.getParameter("flag");
ProgressListener progressListener = new ProgressListener() {
public void update(long pBytesRead, long pContentLength, int pItems) {
float tmp = (float)pBytesRead;
float percentage = tmp/pContentLength*100;
if (percentage >= 100) {
progressMap.put(para, "100");
} else {
progressMap.put(para, percentage + "");
}
}
};
fileUpload.setProgressListener(progressListener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
}
catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
}
catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
}
public String getProgress(String flag) {
return progressMap.get(flag);
}
}
StartController.java:
package com.busymonkey;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class StartController {
@RequestMapping("/hello")
public ModelAndView hello() {
String message = "Hello World, Spring 3.0!";
System.out.println(message);
return new ModelAndView("hello1", "message", message);
}
@RequestMapping("/upload")
public String upLoad(HttpServletRequest request, HttpServletResponse response)
throws IllegalStateException, IOException {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
if (multipartResolver.isMultipart(request)) {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Iterator<String> iter = multiRequest.getFileNames();
while (iter.hasNext()) {
MultipartFile file = multiRequest.getFile((String) iter.next());
if (file != null) {
String fileName = file.getOriginalFilename();
String path = "D:/" + fileName;
File localFile = new File(path);
file.transferTo(localFile);
}
}
}
return "/hello1";
}
@RequestMapping(value = "/getProgress")
@ResponseBody
public String initCreateInfo(HttpServletRequest request) {
CustomMultipartResolver query = new CustomMultipartResolver();
return query.getProgress(request.getParameter("flag"));
}
}
注意:这里因为涉及多线程文件上传,在上传和查询请求的url上加入了flag参数,所以就不使用jsp页面来进行页面上传了,推荐大家使用 chrome 浏览器的 postman 测试工具,使用简单方便。