您当前的位置: 首页 >  spring

Charge8

暂无认证

  • 1浏览

    0关注

    447博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

SpringMVC实现文件上传和下载

Charge8 发布时间:2018-10-03 21:48:58 ,浏览量:1

SpringMVC实现文件上传和下载

文件上传是项目开发中最常见的功能。为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。

Spring MVC 为文件上传提供了直接的支持,这种支持是用即插即用的 MultipartResolver 实现的。Spring MVC 使用 Apache Commons FileUpload技术实现了一个 MultipartResolver 实现类:CommonsMultipartResolver 。因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。

 

 

一、简单文件上传和下载: 文件上传

1)pom.xml 导入依赖:

	
    
        commons-fileupload
        commons-fileupload
        1.3.3
    

2)在springmvc.xml进行配置文件如下:

     SpringMVC上下文中默认没有装配 MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置 MultipartResolver。

     MultipartResolver 用于处理文件上传,当收到请求时 DispatcherServlet 的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中,最后传递给 Controller,在 MultipartResolver 接口中有如下方法:

    

	
	
		
		
			10485760
		
		
		
	

3)编辑上传文件的jsp页面:method="post" enctype="multipart/form-data"

	
文件上传 文件说明: 附件:

4)编写Controller以及处理方法:测试ok

MultipartFile 封装了请求数据中的文件,此时这个文件存储在内存中或临时的磁盘文件中,需要将其转存到一个合适的位置,因为请求结束后临时存储将被清空。在 MultipartFile 接口中有如下方法:

  • String getName();                   // 获取参数的名称
  • String getOriginalFilename(); // 获取文件的原名称
  • String getContentType();        // 文件内容的类型
  • boolean isEmpty();                 // 文件是否为空
  • long getSize();                        // 文件大小
  • byte[] getBytes();                    // 将文件内容以字节数组的形式返回
  • InputStream getInputStream(); // 将文件内容以输入流的形式返回
  • void transferTo(File dest);      // 将文件内容传输到指定文件中
	@RequestMapping(value = "/upload", method = RequestMethod.POST)
	public String upload(String wjsm, @RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
		System.out.println("文件说明:" + wjsm);
		if(!file.isEmpty()) {
			String path = request.getServletContext().getRealPath("/resource/uploadFile");
			//获取上传文件的原名
			String fileName = file.getOriginalFilename(); 
			File desfile = new File(path,fileName);
			if(!desfile.getParentFile().exists()) {
				desfile.getParentFile().mkdirs();
			}
			file.transferTo(new File(path + File.separator + fileName));
		}else {
			System.out.println("文件为空!");
		}
		return "success";
	}
文件下载

文件下载比较简单,可直接在页面给出一个超链接,该链接 href 属性为要下载文件的文件,download 属性可自定义修改下载的文件名。这样就实现文件下载了。

	下载

但是如果该文件的文件名为中文文件名,在某些早起的浏览器上就会导致下载失败;如果使用最新的Firefox、Chrome、Opera、Safari则都可以正常下载文件名为中文的文件了。

SpringMVC提供了一个 ResponseEntity 类型,使用它可以很方便地定义返回的 HttpHeaders 和HttpStatus 。以下代码演示文件的下载功能:

	@RequestMapping(value="/download")
	public ResponseEntity download(HttpServletRequest request, @RequestParam("fileName") String fileName) throws Exception{
		//下载文件路径
		String path = request.getServletContext().getRealPath("/resource/uploadFile");
		File file = new File(path + File.separator + fileName);
		
		HttpHeaders headers = new HttpHeaders();
		//下载显示的文件名,并解决中文名称乱码问题
		String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");
		//通知浏览器以attachment(下载方式)打开
		headers.setContentDispositionFormData("attachment", downloadFileName);
		//applicatin/octet-stream: 二进制流数据(最常见的文件下载)
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		
		return new ResponseEntity(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
	}

另外需要注意的一点:ajax请求无法响应下载功能,我们可构建表单进行提交,下面有使用到。

 

二、实际项目文件上传和下载:

 数据表只保存路径文件和文件名, 上传与下载的文件都存放到约定好的本地磁盘的某个路径下。

tomcat 默认访问运行项目下的资源文件, 无法访问本地磁盘的文件,可通过在 server.xml 配置tomcat虚拟路径来读取。

	   
	   

 页面这样访问即可

附件:${user.fjm } 
文件上传

1)model:忽略校验:

public class User {
	
	private int id;
	
	@NotEmpty(message="用户名不能为空")
	@Pattern(regexp="^\\w{6,18}$",message="用户名必须由6到18位的数字字母或者下划线组成")
	private String username;
	
	@NotNull
	@Length(min=6,max=32,message="密码必须为6到32位的字符串")
	private String password;
	
	@Past
	private Date birthday;
	
	@NotNull(message="年龄不能为空")
	@Max(value=100)
	@Min(value=1)
	private Integer age;
	
	@DecimalMax(value="2.5")
	@DecimalMin(value="1.0")
	private Double height;
	
	@Email
	private String email;
	@NotNull
	private Department department;
	private String fjm;	//附件原名
	private String fjpath; // 附近路径

... }

2)新增页面(表单添加附件上传功能):

	新增用户
	
		用户名:   
		用户密码:   
		email:  
		用户所属部门:  
		生日:  
		年龄:   
		身高: 
		附件:
		 
	

3)controller 处理方法: 忽略校验, 实测ok

	@RequestMapping(value="/add", method = RequestMethod.POST)
	public String addfj(@Valid User user, BindingResult errors, Model model, @RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
		String realpath = "D:\\JQ\\JQuploadfile\\attachments\\";
		String savepath = "t_user";
		String uploadfilepath = realpath + savepath;
		
		//判断数据绑定结果 errors.getErrorCount()>0 也可以
		if (errors.hasFieldErrors()) {
			System.out.println("参数值不合法!");
			// 获得所有的属性错误
			List fieldErrors = errors.getFieldErrors();
			for (FieldError fieldError : fieldErrors) {
				// 把错误信息存放在model对象中
				model.addAttribute(fieldError.getField(), fieldError.getDefaultMessage());
				System.out.println(fieldError.getField() + "===" + fieldError.getDefaultMessage());
				model.addAttribute("departments", departmentService.getAllList());
				return "user-add";
			}
		}
		
		if(!file.isEmpty()) {
			//获取上传文件的原名
			String fileName = file.getOriginalFilename(); 
			File desfile = new File(uploadfilepath,fileName);
			if(!desfile.getParentFile().exists()) {
				desfile.getParentFile().mkdirs();
			}
			file.transferTo(desfile);
			user.setFjm(fileName);
			user.setFjpath(savepath + File.separator + fileName); //保存文件路径
			System.out.println(user);
		}else {
			System.out.println("文件为空!");
		}
		
		userService.add(user);
		return "redirect: /sshweb/users";
	}
文件下载

 查看详情页面提供下载功能 :

1、超链接下载:简单方便

附件:${user.fjm } 

2、SpringMVC下载:可构建表单进行提交

ajax请求无法响应下载功能因为response原因,一般请求浏览器是会处理服务器输出的response,例如生成png、文件下载等,然而ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。文件的下载是以二进制形式进行的,虽然可以读取到返回的response,但只是读取而已,是无法执行的,说白点就是js无法调用到浏览器的下载处理机制和程序。

有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了。下表中列出了一些URL特殊符号及编码

   十六进制值1.+URL 中+号表示空格%2B2.空格URL中的空格可以用+号或者编码%203./分隔目录和子目录%2F4.?分隔实际的 URL 和参数%3F5.%指定特殊字符%256.#表示书签%237.&URL 中指定的参数间的分隔符%268.=URL 中指定参数的值%3D

解决的方法:

replace() 方法如果直接用str.replace("-","!")只会替换第一个匹配的字符. 而str.replace(/\-/g,"!")则可以替换掉全部匹配的字符(g为全局标志)。 replace()

js中替换字符变量如下:

 data2=data2.replace(/\%/g,"%25");  data2=data2.replace(/\#/g,"%23"); data2=data2.replace(/\\{1}/g,"%2F");

代码中可以使用

URLEncoder.encode(url, "UTF-8");

1)jsp页面:method="post" enctype="multipart/form-data"

	查看用户信息
	
		用户编号: 
		用户名: 
		用户密码: 
		email:
		用户所属部门:
		生日:  
		年龄:  
		身高:  

		附件:${user.fjm } 
	


	$("#downloadfj").on("click",function(){
		var _fjpath = $(this).attr("fjpath").replace(/\\{1}/g,"%2F");
		var _url = $(this).attr("url") + "&fjpath=" + _fjpath;
		$("#userShowForm").attr("action",_url).submit();
	});

2)controller 处理方法: 实测ok

	@RequestMapping(value="/download")
	public ResponseEntity download(HttpServletRequest request, @RequestParam("fjm") String fjm, @RequestParam("fjpath") String fjpath) throws Exception{
		String realpath = "D:\\JQ\\JQuploadfile\\attachments\\";
		//下载的文件
		String downloadpathfile = realpath + fjpath;
		File file = new File(downloadpathfile);
		
		HttpHeaders headers = new HttpHeaders();
		//下载显示的文件名,并解决中文名称乱码问题
		String downloadFileName = new String(fjm.getBytes("UTF-8"),"iso-8859-1");
		//通知浏览器以attachment(下载方式)打开
		headers.setContentDispositionFormData("attachment", downloadFileName);
		//applicatin/octet-stream: 二进制流数据(最常见的文件下载)
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		
		return new ResponseEntity(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
	}

数据库信息:

 

 

关注
打赏
1664721914
查看更多评论
立即登录/注册

微信扫码登录

0.3007s