springMVC + ProgressListener + CommonsMultipartResolver 上传进度查询

38 篇文章 0 订阅

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 测试工具,使用简单方便。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,下面是一个使用SpringMVC和Vue.js实现多图片上传的示例代码: 前端页面代码(使用Vue.js): ```html <template> <div> <input type="file" ref="fileInput" @change="handleFileUpload" multiple> <button @click="uploadFiles">上传文件</button> </div> </template> <script> export default { data() { return { files: [] } }, methods: { handleFileUpload() { this.files = this.$refs.fileInput.files; }, uploadFiles() { let formData = new FormData(); for (let i = 0; i < this.files.length; i++) { formData.append("files", this.files[i]); } axios.post("/upload", formData, { headers: { "Content-Type": "multipart/form-data" } }).then(response => { console.log(response.data); }).catch(error => { console.log(error); }); } } } </script> ``` 后端代码(使用SpringMVC): ```java @PostMapping("/upload") @ResponseBody public List<String> upload(@RequestParam("files") MultipartFile[] files) throws IOException { List<String> fileNames = new ArrayList<>(); for (MultipartFile file : files) { if (!file.isEmpty()) { String fileName = file.getOriginalFilename(); String uuid = UUID.randomUUID().toString(); String saveFileName = uuid + "_" + fileName; file.transferTo(new File("/path/to/save/" + saveFileName)); fileNames.add(saveFileName); } } return fileNames; } ``` 这个示例代码使用了Vue.js来实现前端页面的交互,使用了axios库来发送文件上传请求。后端使用了SpringMVCMultipartFile来处理文件上传请求。在处理每个文件时,可以根据需要对文件进行一些额外的处理,例如:获取文件大小、文件类型等。 希望这个示例代码可以帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值