Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 625|回复: 0

SpringMVC 实现文件上传与下载,并配置异常页面

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-9-4 14:06:50 | 显示全部楼层 |阅读模式

    目录


    上传文件的表单要求

    Spring MVC实现上传文件

    需要导入的jar包

    配置MultipartResolver解析器

    编写接收上传文件的控制器

    Spring MVC实现文件下载

    下载文件时的header设置

    编写文件下载的控制器

    Spring MVC配置异常跳转的页面

    配置异常页面的介绍

    配置ExceptionResolver解析器

     

     

     


     

     

     

    上传文件的表单要求

      对于普通表单来说,有几个注意点:

      1、action:表示要提交到哪里;

      2、method:表单提交的方式,常用的有post和get两种,不写的话,默认是get;提交文件是只能使用post方式。

      3、enctype:编码类型,表示提交的数据是什么格式。有三个值,

        1)不显式设置enctype时,默认是application/x-www-form-urlencoded,表示提交的是普通的数据;

        2)text/plain,表示提交的是文本数据,数据量稍大一点。

        3)multipart/form-data,这种方式可以提交二进制数据(音频、图像等文件)

      综上,如果要上传文件,必须要将method设置为post,然后将enctype设置multipart/form-data。另外,上传文件的input标签的type属性设置为file。

    <form action="upload" method="post" enctype="multipart/form-data">
    	<input type="file" name="myfile" />
    	<input type="submit" name="submit" value="upload" />
    </form>
    

      

     

    Spring MVC实现上传文件

      在看Spring MVC是怎么实现文件上传之前,可以先看一下不是框架,使用原生的servlet开发是怎么实现文件上传的:Servlet 实现文件上传与下载

      在Servlet 3.0之后,Spring MVC实现文件上传主要是使用一个叫MultipartResolver的解析器,该解析器依赖于apache的commons-io和commons-fileupload。MultipartResolver会自动解析文件,之后我们在handlerMethod中,可以很方便的操作上传的文件。

     

      需要导入的jar包

      必不可少的commons-io.jar和commons-fileupload.jar这两个包,缺一不可。

     

    配置MultipartResolver解析器

      MultipartResolver是一个interface,我们只需要配置他的一个实现类,比如CommonsMultipartResolver这个实现类,配置的方法也很简单,只需要配置一个id为multipartResolver的<bean>即可。

      在Spring MVC的配置文件中增加下面配置:

    <!-- 创建MultipartResolver解析器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    	<!-- 配置属性,可以省略不配置,设置上传的文件maxSize,单位为B(字节) -->
    	<property name="maxUploadSize" value="1000000"></property>
    </bean>
    

      

      编写接收上传文件的控制器

    package cn.ganlixin.controller;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.UUID;
    
    import org.apache.commons.io.FileUtils;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.multipart.MultipartFile;
    
    @Controller
    public class UploadController {
    
    	@RequestMapping("upload")
    	// 注意表单中文件input的name要和这里的参数名相同。 
    	public String upload(MultipartFile myfile) throws IOException {
    		
    		// 上传一张图片 C:\Users\Administrator\Desktop\code.png
    		
    		// 获取文件的原始名称
    		String originalFileName = myfile.getOriginalFilename();  // code.png
    		
    		// 获取上传文件的表单中,input的name值,其实就是myfile(就是接收时的名称)
    		String fileName = myfile.getName();		// myfile
    		
    		// 获取上传的文件大小,单位为字节
    		long fileSize = myfile.getSize();		// 5823(字节)
    		
    		String extensionName = originalFileName.substring(originalFileName.lastIndexOf("."));
    		
    		/*
    		进行一些过滤判断操作
    		 */
    		
    		// 利用apache的commons-io和commons-fileupload,将文件保存到硬盘中,文件名可以根据自己的规则来定,这里使用UUID
    		String newFileName = UUID.randomUUID().toString();
    		FileUtils.copyInputStreamToFile(
    				myfile.getInputStream(), 
    				new File("E:/uploads/" + newFileName + extensionName)
    		);
    		
    		return "/success.jsp";
    	}
    }
    

      

     

    Spring MVC实现文件下载

      在原生servlet实现文件下载主要有两步:

      1、使用HttpServletRequest对象接收请求,获取客户端想要下载的文件名;

      2、读取需要下载的文件,然后使用HttpServletResponse对象向客户端输出文件的字节流。

      其实Spring MVC实现文件下载和使用原生servlet实现文件下载的方式并没有太大区别,甚至可以说没有任何区别。唯一的区别就是Spring MVC的控制器没有继承HttpServlet,但是却可以为HandlerMethod注入HttpServletRequest和HttpServletResponse对象,之后就可以进行和原生servlet相同的操作了。

     

      下载文件时的header设置

      先看一下提供下载文件的资源链接:

    <a href="download?fileName=info.txt">点击下载info.txt</a>
    <a href="download?fileName=data.rar">点击下载data.rar</a>
    

      如果仍旧按照以前的设置:Content-Type=text/html; charset=utf-8;    那么当客户端点击下载链接时,发生的事情可能超乎预料。上面这两个资源链接的文件的扩展名,扩展名指明了该文件的格式。如果没有设置文件以附件形式下载,那么对于不同的浏览器,对于文件的处理方式是不同的:

      1、如果浏览器能够打开或者能够解析该类型文件,那么,文件就会直接被浏览器打开(注意,不是下载,不会保存到用户的本地磁盘);

      2、如果浏览器不能打开或者不能解析该类型的文件,那么,浏览器才会将文件下载下来(保存到用户磁盘)。

      比如,当服务器响应info.txt之后,浏览器接收到info.txt,info.txt是文本文件,浏览器可以打开,于是就会将info.txt的内容显示在浏览器的页面中,而没有下载下来。而对于data.rar来说,浏览器无法直接打开,所以会下载到本地。

      为了让用户请求下载的文件都能保存到用户磁盘(即使浏览器能够打开文件,也不要让他打开,而只是让他进行下载),可以设置Content-Disposition属性为attachment(通知浏览器以附件形式下载)。

     

      编写文件下载的控制器

    package cn.ganlixin.controller;
    
    import java.io.File;
    import java.io.IOException;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.io.FileUtils;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class DownloadController {
    
    	@RequestMapping("/download")
    	// 注入fileName、request、response
    	public void download(String fileName, 
    			HttpServletRequest request, HttpServletResponse response) throws IOException {
    		
    		// 设置响应是以附件形式,不用设置Content-Type了
    		response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
    		
    		// 获取文件的真实路径(可供下载的文件都放在/project/WebContext/files/路径下,但是部署到服务器后,files文件夹的路径都会发生改变。
    		// 所以需要重新获得该文件从根目录开始的路径,然后读取文件,并响应给客户端。
    		String path = request.getServletContext().getRealPath("files");
    		
    		// 文件下载时,是使用字节流格式,所以不能使用response.getWriter()-->返回PrintWriter是字符流
    		// 获取输出字节流恶意使用response.
    		ServletOutputStream out = response.getOutputStream();
    		File downloadFile = new File(path, fileName);
    		
    		// 判断文件是否存在
    		if (! downloadFile.exists()) {
    			request.setAttribute("msg", "文件不存在");
    			response.sendError(404);
    			return;
    		}
    		
    		// 利用FileUtils将文件读入字节数组,然后返回给客户端。
    		out.write(FileUtils.readFileToByteArray(downloadFile));
    		out.flush();
    		out.close();
    	}
    }
    

      

     

    Spring MVC配置异常跳转的页面

      配置异常跳转页面的介绍

      我们的服务器在运行过程中可能会出现各种异常,当出现异常的时候,根据Java的脾气,一定会打印堆栈信息,这个信息不能直接暴露给用户,一个原因是打印的堆栈信息并不是用户关心的内容,会影响用户体验;另一方面,如果被黑客获取到堆栈信息,也是一种安全隐患。

      所以我们在编程过程中,使用了很多try{   } catch{  },每当出现异常XxxException,可以根据异常的类型,返回给客户一个特定的异常页面。这个返回异常的部分如果直接写在业务代码中也是可以的,但是却不是推荐的。

      Spring MVC提供了一个ExceptionResolver解析器,这个解析器可以为我们做这么一个事情:根据我们自定义的配置,当出现某种Exception的时候,就直接跳转到指定的页面,不需要在逻辑代码中进行处理。

      举个例子:当服务端接收客户端上传的文件时,发现文件的大小超过了设置的最大值,此时,如果配置MultipartResolver时设置了上传文件的最大值,那么此时就会出现org.springframework.web.multipart.MaxUploadSizeExceededException,出现异常时,异常堆栈信息也会显示给客户端,此时就可以配置下ExceptionResolver,当出现这个错误,就跳转到uploadFailed.jsp中。

     

      配置ExceptionResolver解析器

      配置ExceptionResolver解析器的方式也很简单,只需要配置一个id为exceptionResolver的<bean>即可,class可以是ExceptionResolver的一个实现实现类。

    <!-- 配置ExceptionResolver解析器 -->
    <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    	<!-- 配置异常与跳转页面的对应关系 -->
    	<property name="exceptionMappings">
    		<props>
    			<prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">/uploadFailed.jsp</prop>
    		</props>
    	</property>
    </bean>
    

      

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 13:39 , Processed in 0.057181 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表