SpringMVC 文件的上传、下载

 

文件上传

(1)下载添加2个jar包

  • commons-fileupload.jar
  • commons-io.jar

SpringMVC的文件上传依赖于Apache的FileUpload组件,须要下载添加2个jar包,下载地址:前端

http://commons.apache.org/proper/commons-fileupload/web

http://commons.apache.org/proper/commons-io/spring

 

 

(2)表单

  <form action="${pageContext.request.contextPath}/fileUpload" method="post" enctype="multipart/form-data">
    选择文件:<input name="uploadFile" type="file" multiple /><br />
    <button type="submit">上传</button>
  </form>

multiple用于文件多选,不使用multiple则只能选择一个文件。apache

 

 

(3)controller

@org.springframework.stereotype.Controller
public class FileUploadController{

    @RequestMapping("/fileUpload")
    public String fileUpload(@RequestParam("uploadFile") List<MultipartFile> fileList, HttpServletRequest request) {
        //若是用户上传了文件
        if (!fileList.isEmpty() && fileList.size()>0){
            System.out.println(fileList.isEmpty());
            System.out.println(fileList.size());
            //设置保存路径为项目根目录下的upload文件夹
            String savePath = request.getServletContext().getRealPath("/upload");
            //不存在就新建
            File saveDir = new File(savePath);
            if (!saveDir.exists()){
                saveDir.mkdirs();
            }

            //循环读取上传文件并保存
            for (MultipartFile file:fileList){
                //原文件名
                String originalFilename = file.getOriginalFilename();
                //使用uuid防止文件重名,由于原文件名中包含扩展名,只能放最后面
                String newFilename= UUID.randomUUID()+"_"+originalFilename;
                System.out.println(originalFilename);
                //将临时文件保存至指定目录
                try {
                    file.transferTo(new File(saveDir+"/"+newFilename));
                } catch (IOException e) {
                    e.printStackTrace();
                    return "error";
                }

            }
            return "success";
        }
        //若是用户未上传文件,返回error
        return "error";
    }

}

SpringMVC用MultipartFile来封装上传文件,一个MultipartFile对应一个上传文件。浏览器

 

 

(4)SpringMVC的配置文件

<?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 https://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="com.chy.controller" />

    <!--注解驱动,自动注册HandlerMapping、HandlerAdapter-->
    <mvc:annotation-driven />

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!--后缀-->
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 配置MultipartResolver,bean的id或name必须为multipartResolver -->
    <bean name="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 上传文件使用的编码字符集-->
        <property name="defaultEncoding" value="utf-8" />
        <!-- 所容许上传文件的最大尺寸,单位字节-->
        <property name="maxUploadSize" value="10485760" />
    </bean>
    
</beans>

只需配置MultipartResolver。spring-mvc

 

 


 

 

文件下载

(1)前端传递文件名

<a href="${pageContext.request.contextPath}/download?filename=1.jpg">下载文件</a>

 

 

(2)controller

@org.springframework.stereotype.Controller
public class DownloadController{

    @RequestMapping("/download")
    public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) throws IOException {
        //指定存放文件的路径,此路径是在部署项目下,/表示部署项目的根路径
        String dir=request.getServletContext().getRealPath("/files");
        File file = new File(dir + "/" + filename);

        //设置响应头
        HttpHeaders httpHeaders = new HttpHeaders();
        //通知浏览器如下载的方式处理,第二个参数指定文件名
        httpHeaders.setContentDispositionFormData("attachment", filename);
        //以流的形式返回
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        //读取目标文件
        byte[] arr = FileUtils.readFileToByteArray(file);
        //建立ResponseEntity对象并返回。目标文件的byte[]、HttpHeaders、Http状态码
        return new ResponseEntity<>(arr, httpHeaders, HttpStatus.OK);
    }

}

 

读取目标文件为byte[ ],使用的FileUtils是commons-io.jar中的类,因此要添加commons-io.jar。mvc

 

也能够使用jdk自带的方式读取目标文件为byte[ ]:app

    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] arr = fileInputStream.readAllBytes();

不须要添加额外的jar包。dom

 

 


 

 

解决下载文件,中文文件名乱码的问题

上面的代码,若是文件名中有中文,文件名会乱码。jsp

 

缘由在于此句代码中的文件名未指定编码字符集:

 

httpHeaders.setContentDispositionFormData("attachment", filename);

浏览器拿到文件名,发现没有指定字符集,就使用浏览器默认的字符集,

不少浏览器的默认字符集是ISO-8859,不包含中文字符,没法处理文件名里的中文,从而文件名乱码。

 

 

解决方式:

httpHeaders.setContentDispositionFormData("attachment", URLEncoder.encode(filename,"utf-8"));

对文件名使用utf-8编码。

 

此种方式只对部分浏览器有效。

不一样的浏览器,默认的编码字符集可能不一样,解决方式也可能不一样,须要根据User-Agent(浏览器内核)来分别处理。