spring 以表单方式提交的文件上传

本文详细介绍如何在Spring MVC框架中实现文件的上传与下载功能,包括必要的依赖配置、控制器处理逻辑及前端页面设计,特别关注了中文文件名的正确处理。

以表单方式提交的文件上传

基本概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

额外jar包

在这里插入图片描述

<!--文件上传-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>

spring-mvc-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: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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 配置扫描的包 -->
    <context:component-scan base-package="org.songwang"/>
    <!--配置注解驱动  -->
    <mvc:annotation-driven />
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="org.songwang.interceptor.MainInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    
    <!-- 文件上传和拦截器配置没有关系-->
    <!--配置文件上传解析器  id 名称必须为multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置请求的编码格式-->
        <property name="defaultEncoding" value="UTF-8"></property>
    </bean>
</beans>

文件上传Controller处理逻辑

package org.songwang.controller;

import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.UUID;

/**
 * 〈一句话功能简述〉
 * 〈功能详细描述〉
 *
 * @ClassName [FileUploadController]
 * @Description [TODO]
 * @Author [single_kitty]
 * @Date [2019/1/14 22:54]
 * @Version [v1.0]
 **/
@Controller
public class FileUploadController {

	/**
	 * 文件上传
	 *
	 * @return
	 */
	@PostMapping("/fileUpload")
	public String fileUpload(@RequestParam("userName") String userName,
	                         @RequestParam("uploadFiles") List<MultipartFile> uploadFiles,
	                         HttpServletRequest request) {
		// 判断文件是否存在
		if (!uploadFiles.isEmpty() && uploadFiles.size() > 0) {
			// 循环输出上传文件
			for (MultipartFile file : uploadFiles){
				// 获取原始的文件名称
				String originalFilename = file.getOriginalFilename();
				// 设置上传文件的保存目录
				String uploadPath = request.getServletContext().getRealPath("/upload/");
				File filePath = new File(uploadPath);
				System.out.println(uploadPath);

				if(!filePath.exists()){
					// 如果目录不存在就创建
					filePath.mkdir();
				}
				// 使用uuid重新命名上传文件的文件名称(上传人_uuid_文件名)
				String newFileName = userName + "_"+UUID.randomUUID()+"_"+originalFilename;

				try {
					// 使用MultipartFile接口的方法完成文件上传到指定位置
					file.transferTo(new File(filePath+"\\"+newFileName));
					System.out.println(filePath+"\\"+newFileName);
				} catch (IOException e) {
					e.printStackTrace();
					return "error";
				}
			}
			return "success";

		}
		return "error";
	}

	@RequestMapping("/download")
	public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,
	                                           String filename) throws Exception{
	    // 指定要下载的文件所在路径
	    String path = request.getServletContext().getRealPath("/upload/");
	    // 创建该文件对象
	    File file = new File(path+File.separator+filename);


		// 对文件名编码,防止中文文件乱码
		filename = this.getFilename(request, filename);

		// 设置响应头
	    HttpHeaders headers = new HttpHeaders();
	    // 通知浏览器以下载的方式打开文件
	    headers.setContentDispositionFormData("attachment", filename);
	    // 定义以流的形式下载返回文件数据
	    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
	    // 使用Sring MVC框架的ResponseEntity对象封装返回下载数据
	   return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
	                                                       headers,HttpStatus.OK);
	}
	/**
	 * 根据浏览器的不同进行编码设置,返回编码后的文件名
	 */
	public String getFilename(HttpServletRequest request,
	                          String filename) throws Exception {
		// IE不同版本User-Agent中出现的关键词
		String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
		// 获取请求头代理信息
		String userAgent = request.getHeader("User-Agent");
		for (String keyWord : IEBrowserKeyWords) {
			if (userAgent.contains(keyWord)) {
				//IE内核浏览器,统一为UTF-8编码显示
				return URLEncoder.encode(filename, "UTF-8");
			}
		}
		//火狐等其它浏览器统一为ISO-8859-1编码显示
		return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
	}

}

前端页面

<%--
  Created by IntelliJ IDEA.
  User: single_kitty
  Date: 2019/1/14
  Time: 12:01
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.net.URLEncoder" %>
<html>
<head>
    <title>主页面-拦截器测试</title>
</head>
<body>
    <p>${USER_SESSION.userName}</p>
    <a href="${pageContext.request.contextPath}/loginOut">退出登陆</a>

    <%--表单方式完成文件的上传和下载--%>
    <form action="${pageContext.request.contextPath}/fileUpload"
          method="post"
          enctype="multipart/form-data"
          "checkUpload()">
        用户名:<input type="text" name="userName" id="userName"><br/>
        上传文件:<<input type="file" name="uploadFiles" id="uploadFiles"><br/>
        <input type="submit" value="上传">
    </form>

    <%--<a
    href="${pageContext.request.contextPath}/download?filename=xiaobai_72165431-37c9-459c-b7a9-ce0d2077b04e_吉佑社 - 不爱又何必纠缠.mp3">
    下载</a>--%>
    <a href="${pageContext.request.contextPath }/download?filename=<%=
                                   URLEncoder.encode("xiaobai_72165431-37c9-459c-b7a9-ce0d2077b04e_吉佑社 - 不爱又何必纠缠.mp3", "UTF-8")%>">
        下载
    </a>

    <script>
        function checkUpload(){
            var userName = document.getElementById("userName");
            var uploadFiles = document.getElementById("uploadFiles");

            if(userName ==''){
                alert("请输入用户名");
                return false;
            }
            if(uploadFiles=='' || uploadFiles.length == 0){
                alert("请选择上传的文件");
                return false;
            }
            return true;
        }
    </script>
</body>
</html>

注意在处理中文文件名的上传下载需要注意以下几点

  1. 前端传递的文件名和后端的编码要一致(中文都指定为UTF-8

      <a href="${pageContext.request.contextPath }/download?filename=<%=
                                       URLEncoder.encode("xiaobai_72165431-37c9-459c-b7a9-ce0d2077b04e_吉佑社 - 不爱又何必纠缠.mp3", "UTF-8")%>">
            下载
        </a>
    
  2. 后端在处理中文文件名的时候,根据不同的浏览器设置不同,主要时由于ie

       //.....
    	
    		// 对文件名编码,防止中文文件乱码
    		filename = this.getFilename(request, filename);
    	//...
    
    	/**
    	 * 根据浏览器的不同进行编码设置,返回编码后的文件名
    	 */
    	public String getFilename(HttpServletRequest request,
    	                          String filename) throws Exception {
    		// IE不同版本User-Agent中出现的关键词
    		String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
    		// 获取请求头代理信息
    		String userAgent = request.getHeader("User-Agent");
    		for (String keyWord : IEBrowserKeyWords) {
    			if (userAgent.contains(keyWord)) {
    				//IE内核浏览器,统一为UTF-8编码显示
    				return URLEncoder.encode(filename, "UTF-8");
    			}
    		}
    		//火狐等其它浏览器统一为ISO-8859-1编码显示
    		return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
    	}
    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值