Spring MVC文件上传

24 篇文章 0 订阅
24 篇文章 0 订阅

1.场景

      实现单个文件上传和多个文件上传的功能,另外还可以预览上传到服务器上的图片,点击预览的某个图片,打开新的Tab看原图,如下图:

      多文件上传,一次可以选择多个图片

     

        单个文件上传,也就一次只能选择上传一张图片!

        图片预览,这是我自己写的一个图片预览控件,感兴趣的话,可以看项目DEMO

      

         点击预览的某张图片,打开新的Tab查看原图,如下

 

2.导入相关包

Sping MVC的文件上传功能依赖commons-fileupload.jar、commons-logging.jar、commons-lang.jar、commons-io.jar,另外上传的图片要进行预览的话,那就可能要用到jstl标签库的标签,进行for循环读取图片,所以就需要导入jstl.jar和standard.jar包,以及Spring MVC相关的jar包,如下图:

 

POM.xml添加的依赖包如下:

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<junit.version>3.8.1</junit.version>
		<javax.servlet.version>2.5</javax.servlet.version>
		<!-- 源代码Java编译版本 -->
		<maven.compiler.source.version>1.7</maven.compiler.source.version>
		<!-- 目标平台Java编译版本 -->
		<maven.compiler.target.version>1.7</maven.compiler.target.version>
		<spring.version>4.3.9.RELEASE</spring.version>
		<commons.logging.version>1.2</commons.logging.version>
		<javax.servlet.jsp.version>2.2</javax.servlet.jsp.version>
		<jstl.jstl.version>1.2</jstl.jstl.version>
		<taglibs.standard.version>1.1.2</taglibs.standard.version>
		<commons-lang.version>2.6</commons-lang.version>
		<commons-fileupload.commons-fileupload.version>1.3.1</commons-fileupload.commons-fileupload.version>
		<org.slf4j.slf4j-log4j12.version>1.7.2</org.slf4j.slf4j-log4j12.version>
		<jackson.version>2.5.4</jackson.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>${javax.servlet.version}</version>
			<scope>provided</scope> <!-- scope=provided 在编译和测试的过程有效,最后项目打包时不会加入 -->
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>${javax.servlet.jsp.version}</version>
			<scope>provided</scope> <!-- scope=provided 在编译和测试的过程有效,最后项目打包时不会加入 -->
		</dependency>
		<!-- sl4j日志包 -->
		<!--  
		     slf4j-log4j12-版本号.jar 依赖以下两个包,也会自动添加进来
		     slf4j-api-版本号.jar
             log4j-版本号.jar
                          例如:slf4j-log4j12-1.7.2.jar,就依赖slf4j-api-1.7.2.jar和log4j-1.2.17.jar这两个包
        -->
		<dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-log4j12</artifactId>  
            <version>${org.slf4j.slf4j-log4j12.version}</version>  
        </dependency> 
		<!-- end  -->
		<!-- common包 -->
		<dependency>
		    <groupId>commons-logging</groupId>
		    <artifactId>commons-logging</artifactId>
		    <version>${commons.logging.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>${commons-lang.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>${commons-fileupload.commons-fileupload.version}</version>
		</dependency>
		<!-- end -->
		<!-- JSTL标签库 -->
		<dependency>
		    <groupId>jstl</groupId>
		    <artifactId>jstl</artifactId>
		    <version>${jstl.jstl.version}</version>
		</dependency>
		<dependency>
		    <groupId>taglibs</groupId>
		    <artifactId>standard</artifactId>
		    <version>${taglibs.standard.version}</version>
		</dependency>	
		<!-- end -->
		<!-- JACKSON包,让Spring MVC支持JSON视图的解析以及返回JSON数据进行呈现 -->
	    <!--  
		     jackson-databind-版本号.jar 依赖以下两个包,也会自动添加进来
		     jackson-annotations-版本号.jar
             jackson-core-版本号.jar
                          例如:jackson-databind-2.5.4.jar,就依赖jackson-annotations-2.5.0.jar和jackson-core-2.5.4.jar这两个包
        -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.version}</version>
		</dependency>	
		<!-- end -->
 		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-aop</artifactId>
	        <version>${spring.version}</version>	        
		</dependency>
		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-beans</artifactId>
	        <version>${spring.version}</version>
		</dependency>	
		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-context</artifactId>
	        <version>${spring.version}</version>	        
		</dependency>	
		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-core</artifactId>
	        <version>${spring.version}</version>	        
		</dependency>	
		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-expression</artifactId>
	        <version>${spring.version}</version>	        
		</dependency>			
		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-web</artifactId>
	        <version>${spring.version}</version>	        
		</dependency>	
		<dependency>
		    <groupId>org.springframework</groupId>
	        <artifactId>spring-webmvc</artifactId>
	        <version>${spring.version}</version>	        
		</dependency>	 												
	</dependencies>

 

 

 

3.Spring MVC配置文件上传解析器

因为要用到jsp页面上传文件,所以肯定也需要配置JSP视图解析器和静态资源处理,配置如下:

 

        <!-- 静态资源处理, css, js, imgs,html 等-->
	<mvc:resources location="/resources/" mapping="/resources/**"  />
	
        <!-- Jsp视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	    <!-- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> -->
	    <property name="order" value="2" />
		<property name="prefix" value="/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
	
	<!-- 文件上传解析器 -->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- maxUploadSize 文件附件的大小最大限制,maxUploadSize=-1 表示无穷大,单位是byte。本案例,限制的最大附件为50M -->
		<property name="maxUploadSize" value="52428800" />
		<property name="defaultEncoding" value="UTF-8" />
		<!-- resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 -->
		<property name="resolveLazily" value="true" />
	</bean>

 

 

 

 

4、处理上传的文件的Controller

该案例Demo是做图片的上传和预览,所以Controller必须对上传的文件类型进行限制,只能上传图片!!

FileUploadController.java:

 

package edu.mvcdemo.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
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.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import edu.mvcdemo.utils.FileComparator;

/**
 * @编写人: yh.zeng
 * @编写时间:2017-7-16 上午11:05:27
 * @文件描述: 文件上传demo,通过代码控制,限制了只能上传图片
 */
@Controller
@Scope("singleton") //只实例化一个bean对象(即每次请求都使用同一个bean对象),默认是singleton
public class FileUploadController {
	
	private Logger logger = LoggerFactory.getLogger(FileUploadController.class);
	
	//从properties配置文件读取file.uploadpath的属性值并给字段赋值,默认值为E:\\360Downloads\\temp
	@Value("${file.uploadpath:E:\\360Downloads\\temp}")
	private String uploadpath;
	//从properties配置文件读取character.encoding的属性值并给字段赋值,默认值为UTF-8
	@Value("${character.encoding:UTF-8}")
	private String characterEncoding;
	
    /**
     * 跳转至多文件上传页面
     * @return
     */
	@RequestMapping(value="/admin/mutilpartfile", method=RequestMethod.GET, params="upload")
	private String showUploadPage(){
		return "mutilpartfile-upload";
	}
	
    /**
     * 跳转至单个文件上传页面
     * @return
     */
	@RequestMapping(value="/admin/onefile", method=RequestMethod.GET, params="upload")
	private String showUploadPage2(HttpServletRequest request){
		return "onefile-upload";
	}
	
	/**
	 * 单文件上传处理
	 * @param files
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/onefile/upload", method=RequestMethod.POST)
	private String uploadOneFile(@RequestParam("file1") MultipartFile file) throws Exception {
		
		String fileName = file.getOriginalFilename();
		File targetDir = new File(uploadpath);
		if (!targetDir.exists()) {
			targetDir.mkdirs();
		}

		if (!fileName.toLowerCase().endsWith(".jpg")
				&& !fileName.toLowerCase().endsWith(".png")
				&& !fileName.toLowerCase().endsWith(".bmp")
				&& !fileName.toLowerCase().endsWith(".gif")) {
			throw new Exception("不是支持的文件类型!只支持图片上传!");
		}

		File targetFile = new File(uploadpath + File.separator + UUID.randomUUID() + "_" + fileName);
		logger.info("上传图片:{}", targetFile.getPath());
		file.transferTo(targetFile);
			
		return "redirect:/uploaded-files/preview";
	}
	

	/**
	 * 多文件上传处理
	 * @param files
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/mutilpartfile/upload", method=RequestMethod.POST)
	private String uploadMutilpartFile(@RequestParam("file1") MultipartFile files[]) throws Exception {
		for(MultipartFile file : files){
			String fileName = file.getOriginalFilename();
			File targetDir = new File(uploadpath);
			if(!targetDir.exists()){
				targetDir.mkdirs();
			}
			
			if(!fileName.toLowerCase().endsWith(".jpg") 
			    && !fileName.toLowerCase().endsWith(".png")
			    && !fileName.toLowerCase().endsWith(".bmp")
			    && !fileName.toLowerCase().endsWith(".gif")
			){
				throw new Exception("不是支持的文件类型!只支持图片上传!");
			}
			
			File targetFile = new File(uploadpath + File.separator + UUID.randomUUID() + "_" + fileName);
			logger.info("上传图片:{}", targetFile.getPath());
			file.transferTo(targetFile);
			
		}
		return "redirect:/uploaded-files/preview";
	}
	
	
	/**
	 * 返回服务器上要预览的某张图片
	 * @param fileName
	 * @param fileType
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value="/uploaded-files/preview/{fileType}/{fileName}", method=RequestMethod.GET)
	private void previewImg(@PathVariable("fileName") String fileName, @PathVariable("fileType") String fileType,
			HttpServletResponse response) throws Exception{
	    fileName = new String(fileName.getBytes("ISO-8859-1"), characterEncoding);  //解决get方式中文乱码
		logger.info("预览图片:{}{}{}.{}", uploadpath, File.separator, fileName, fileType);
		BufferedImage image = ImageIO.read(new File(uploadpath + File.separator + fileName + "." + fileType));
		
		switch(fileType.toLowerCase()){
		       case "jpg":
		    	   response.setContentType("image/jpeg");
		    	   break;
		       case "png":
		    	   response.setContentType("image/png");
		    	   break;
		       case "bmp":
		    	   response.setContentType("image/bmp");
		    	   break;
		       case "gif":
		    	   response.setContentType("image/gif");
		    	   break;
		       default:
		    	   throw new Exception("不是支持的文件类型!只支持预览图片!");
		}
		
		ImageIO.write(image, fileType , response.getOutputStream());
	}
	
	
	/**
	 * 预览已上传的所有图片
	 * @return
	 */
	@RequestMapping(value="/uploaded-files/preview")
	private ModelAndView listUploadedImg(){
		File dir = new File(uploadpath);
		if(!dir.exists()){
			dir.mkdirs();
		}
		
		//获取该文件夹下的图片
		File fileArr[] = dir.listFiles(new FileFilter(){

			@Override
			public boolean accept(File file) {
				String fileName = file.getName().toLowerCase();
				if(fileName.endsWith(".jpg") 
				    || fileName.endsWith(".png")
				    || fileName.endsWith(".bmp")
				    || fileName.endsWith(".gif")
				){
					return true;
				}else{
					return false;
				}
			}
			
		});
		
		List<File> fileList = Arrays.asList(fileArr);
		Collections.sort(fileList, new FileComparator());
		
		String imgFileNames[] = new String[fileArr.length];  //文件名,去除后缀
		String imgFileTypes[] = new String[fileArr.length];  //文件类型
		for(int i = 0; i < fileArr.length; i++){
			String fileName = fileArr[i].getName();
			imgFileNames[i] = fileName.substring(0, fileName.lastIndexOf("."));
			imgFileTypes[i] = fileName.substring(fileName.lastIndexOf(".")+1, fileName.length());
			
		}
		
		ModelAndView modelAndView =  new ModelAndView("preview-uploaded-files");
		modelAndView.addObject("imgFileNames", imgFileNames);
		modelAndView.addObject("imgFileTypes", imgFileTypes);
		
		return modelAndView;
	}
	
}

 

本案例中,是将上传到服务器上的图片保存到磁盘中,所以做图片预览的时候,是从磁盘上取图片列表,返回到页面上展示。从磁盘上读取文件的代码,请看listUploadedImg方法。此外,在页面上展示图片的先后顺序肯定也要考虑的,这里就按照图片的最后修改时间进行降序排序(即最后上传的图片,展示在最前面)。

排序使用的是Collections.sort方法,如下

 

		List<File> fileList = Arrays.asList(fileArr);
		Collections.sort(fileList, new FileComparator());

FileComparator.java的代码如下:

 

 

package edu.mvcdemo.utils;

import java.io.File;
import java.util.Comparator;

/**
 * @编写人: yh.zeng
 * @编写时间:2017-7-20 上午12:55:34
 * @文件描述: 文件列表按照最后修改时间降序排序
 */
public class FileComparator implements Comparator<File>  {

	@Override
	public int compare(File file1, File file2) {
		long time1 = file1.lastModified();  
		long time2 = file2.lastModified(); 
		
		if(time1 == time2){
			return 0;
		}else if(time1 > time2){
			return -1;
		}else{
			return 1;
		}
	}

}

 

 

 

5.文件上传的Jsp页面

由于该案例Demo是图片上传与预览的功能,所以页面上必须对上传的文件类型进行限制,只能上传图片!!

单个文件上传的页面onefile-upload.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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>当个文件上传demo,本案例限制了只能上传图片</title>
<script type="text/javascript">
     function checkFile(el){
    	 var files = el.files;  //获取选择的文件对象
    	 var allowTypes = ["image/jpeg","image/png","image/x-png","image/bmp","image/gif"]; //允许上传的文件类型
    	 var maxFileSize = 50 * 1024 * 1024;  //允许上传的单个文件的大小限制,最大能上传50M
    	 var allowUpload = true; //经过校验之后是否允许上传
    	 var errorMessage = "";  //校验文件之后,文件不符合要求的提示信息
    	 
    	 for(var i=0; i< files.length; i++){
    	      var fileName = files[i].name;    //文件名
    	      var fileType = files[i].type;    //文件类型
    	      var fileSize = files[i].size;    //文件大小,单位为byte(字节)
    	      
    	      var typeAccepted = false;
    	      for(var j = 0; j < allowTypes.length; j++){
    	    	  if(allowTypes[j] == fileType){
    	    		  typeAccepted = true;
    	    		  break;
    	    	  }
    	      }
    	      if(typeAccepted != true){
    	    	  errorMessage += fileName + "不是图片,只能上传图片!";
    	    	  allowUpload = false;
    	      }
    	      
    	      if(typeAccepted && fileSize > maxFileSize){
    	    	  errorMessage += fileName+"的文件大小超出了50M限制!";
    	    	  allowUpload = false;
    	      }
    	 }
    	 
    	 if(allowUpload != true){
    		 el.outerHTML = el.outerHTML; //清空选择的文件
    		 alert(errorMessage);
    	 }
     }
     
     function checkForm(){
    	 if(document.getElementById("file1").value == ""){
    		 alert("请选择要上传的文件!");
    		 return false;
    	 }
    	 return true;
     }
</script>
</head>
<body>
   <form action="${pageContext.request.contextPath}/onefile/upload" method="post" enctype="multipart/form-data" onsubmit="return checkForm();">
        <input type="file" name="file1" id="file1" onchange="checkFile(this)"/> <br>
        <input type="submit" value="提交"/>
   </form>
</body>
</html>


多个文件上传的页面mutilpartfile-upload.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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>多文件上传demo,本案例限制了只能上传图片</title>
<script type="text/javascript">
     function checkFile(el){
    	 var files = el.files;  //获取选择的文件对象
    	 var allowTypes = ["image/jpeg","image/png","image/x-png","image/bmp","image/gif"]; //允许上传的文件类型
    	 var maxFileSize = 50 * 1024 * 1024;  //允许上传的单个文件的大小限制,最大能上传50M
    	 var allowUpload = true; //经过校验之后是否允许上传
    	 var errorMessage = "";  //校验文件之后,文件不符合要求的提示信息
    	 
    	 for(var i=0; i< files.length; i++){
    	      var fileName = files[i].name;    //文件名
    	      var fileType = files[i].type;    //文件类型
    	      var fileSize = files[i].size;    //文件大小,单位为byte(字节)
    	      
    	      var typeAccepted = false;
    	      for(var j = 0; j < allowTypes.length; j++){
    	    	  if(allowTypes[j] == fileType){
    	    		  typeAccepted = true;
    	    		  break;
    	    	  }
    	      }
    	      if(typeAccepted != true){
    	    	  errorMessage += fileName + "不是图片,只能上传图片!";
    	    	  allowUpload = false;
    	      }
    	      
    	      if(typeAccepted && fileSize > maxFileSize){
    	    	  errorMessage += fileName+"的文件大小超出了50M限制!";
    	    	  allowUpload = false;
    	      }
    	 }
    	 
    	 if(allowUpload != true){
    		 el.outerHTML = el.outerHTML; //清空选择的文件
    		 alert(errorMessage);
    	 }
     }
     
     function checkForm(){
    	 if(document.getElementById("file1").value == ""){
    		 alert("请选择要上传的文件!");
    		 return false;
    	 }
    	 return true;
     }
</script>
</head>
<body>
   <form action="${pageContext.request.contextPath}/mutilpartfile/upload" method="post" enctype="multipart/form-data" onsubmit="return checkForm();">
        <input type="file" name="file1" id="file1" multiple="multiple" onchange="checkFile(this)"/> <br>
        <input type="submit" value="提交"/>
   </form>
</body>
</html>

 

 

 

6.文件预览的Jsp页面

preview-uploaded-files.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 
<%@ taglib prefix="image" uri="http://yh.zeng/tag/image" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>预览上传到服务器上的图片</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/jquery-3.2.1.min.js"></script>
<style>
   .imgBorder{
       float: left;
       border: 1px solid gray;
       margin-top:5px;
       margin-right: 5px;
       padding: 10px;
       color: gray;
       font-size: 10px;
   }
   .imgClass{
       cursor: pointer;
   }
</style>
<script type="text/javascript">
   $(function(){
	   $("img.imgClass").click(function(){
            window.open($(this).attr("src"));
	   });
   });
</script>
</head>
<body>
<c:forEach items="${requestScope.imgFileNames}" var="fileName" varStatus="i">
   <div class="imgBorder">
      ${fileName}.${requestScope.imgFileTypes[i.index]}<br>
      <image:scale src="${pageContext.request.contextPath}/uploaded-files/preview/${requestScope.imgFileTypes[i.index]}/${fileName}" styleClass="imgClass" width="300"/>
   </div>
</c:forEach>
</body>
</html>

 

 

 

7.效果

单个文件上传

http://localhost:8080/MavenSpringMvcDemo/admin/onefile?upload

多个文件上传

http://localhost:8080/MavenSpringMvcDemo/admin/mutilpartfile?upload

上传到服务器上的图片预览,图片缩放的控件,是我自己写的控件,感兴趣的童鞋可以看项目DEMO

http://localhost:8080/MavenSpringMvcDemo/uploaded-files/preview

点击某个预览的图片,查看原图

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值