Spring MVC代码实例系列-10:Spring MVC实现简单的文件上传和下载

超级通道 :Spring MVC代码实例系列-绪论

本章主要记录Spring MVC实现简单的文件上传和下载。涉及到的知识点有:
- CommonsMultipartResolver:通用多部件解析器,用来实现多文件上传
- MultipartFile:多部件文件,用来传输多种类型的文件
- 两种文件保存方式:1.通过BufferedOutputStream写入服务器。2.通过MultipartFile封装的方法写入。
- 两种文件下载方式:通过设置Content-Dispositioninlineattachment试下浏览器显示和文件下载。

1.文件上传

1.1.spring-mvc-servlet.xml

添加CommonsMultipartResolver,用于解析POST请求中的MultiPartFile.

<!--文件上传-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--一次上传限制10Mb(一次可以上传多种多个文件)-->
    <property name="maxUploadSize" value="10485760"/>
    <property name="defaultEncoding" value="utf-8"/>
</bean>

1.2.FileUtils.java

两种上传方式
1. saveFileByStream通过原生的BufferedOutputStream将将文件保存在服务器
2. saveFileByMultiPartFile通过MultiPartFile.transferTo()将文件保存

package pers.hanchao.hespringmvc.file;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>简单的文件上传和下载实例,
 * 文件上传实现了两种方式的上传:流和MultiPartFile;
 * 文件下载实现了两种方式的下载:inline和attachment</p>
 * @author hanchao 2018/1/24 22:35
 **/
@Component
@RequestMapping("file")
public class FileUtils {

    private static final Logger LOGGER = Logger.getLogger(FileUtils.class);

    /**
     * <p>上传文件的两种方式:流上传和Multipart上传</p>
     * @author hanchao 2018/1/22 22:22
     **/
    @PostMapping("/upload")
    public String upload(HttpServletRequest request, @RequestParam("file") MultipartFile[] files,Model model){
        boolean isSuccess = true;
        //获取上传根目录
        String uploadRootPath = request.getServletContext().getRealPath("upload");
        LOGGER.debug("uploadRoot:" + uploadRootPath);
        File uploadRootDir = new File(uploadRootPath);
        //判断上传根目录是否存在,如果不存在,则创建层级目录
        if (!uploadRootDir.exists()){
            uploadRootDir.mkdirs();
        }
        //上传文件
        List<File> savedFileList = new ArrayList<File>();
        for (int i = 0; i < files.length; i++) {
            MultipartFile file = files[i];
            //如果文件大于200kb,则不能上传
            if (file.getSize() > 204800){
                isSuccess = false;
                break;
            }
            /*
            两种上传方式
            1.saveFileByStream通过原生的BufferedOutputStream将将文件保存在服务器
            2.saveFileByMultiPartFile通过MultiPartFile.transferTo()将文件保存
             */
            File savedFile = saveFileByStream(file, uploadRootDir);
//            File savedFile = saveFileByMultiPartFile(file, uploadRootDir);
            savedFileList.add(savedFile);
        }
        if (!isSuccess){
            model.addAttribute("returnMessage","文件太大,禁止上传!");
            LOGGER.error("文件太大,禁止上传!");
        }else {
            model.addAttribute("savedFileList",savedFileList);
        }
        return "/file/file";
    }

    /**
     * <p>通过流操作保存文件</p>
     * @param srcFile 需要保存的文件
     * @param uploadRootDir 上传文件根目录
     * @return 上传完的文件
     * @author hanchao 2018/1/22 22:09
     **/
    private File saveFileByStream(MultipartFile srcFile, File uploadRootDir) {
        //获取客户端名称
        String srcFileName = srcFile.getOriginalFilename();
        LOGGER.debug("客户端文件名称:" + srcFileName);

        File serverFile = null;
        if (srcFileName != null && srcFileName.length() > 0){
            try{
                byte[] bytes = srcFile.getBytes();
                //创建服务器文件
                serverFile = new File(uploadRootDir.getAbsolutePath() + File.separator + srcFileName);
                //写入服务器文件
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(serverFile));
                bos.write(bytes);
                bos.close();
                //打印上传了哪些文件
                LOGGER.info("写入了文件:" + serverFile);
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.error("删除文件失败!");
            }
        }
        return serverFile;
    }

    /**
     * <p>通过MultipartFile的封装方法保存文件</p>
     * @param srcFile 需要保存的文件
     * @param uploadRootDir 上传文件根目录
     * @return 上传完的文件
     * @author hanchao 2018/1/23 22:09
     **/
    public File saveFileByMultiPartFile(MultipartFile srcFile, File uploadRootDir){
        File serverFile = null;
        //如果文件不为空,则可以上传
        if (!srcFile.isEmpty()){
            try{
                serverFile = new File(uploadRootDir.getAbsolutePath() + File.separator + srcFile.getOriginalFilename());
                srcFile.transferTo(serverFile);
                //打印上传了哪些文件
                LOGGER.info("写入了文件:" + serverFile);
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.error("删除文件失败!");
            }
        }
        return serverFile;
    }
}

1.3.file.jsp

注意:
1. 一定要注意设置enctype="multipart/form-data"
2. 一定要注意name="file"要与后台传参对应,如@RequestParam("file") MultipartFile[] files

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: hanchao
  Date: 2018/1/22
  Time: 21:16
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
    <title>文件上传下载</title>
    <style type="text/css">
        div {margin: 5px 5px;text-align:center; border:1px solid #96c2f1; background:#eff7ff;}
    </style>
</head>
<body>
<div style="width: 600px;">
    <h3>文件上传和下载实例</h3>
</div>
<div style="width: 290px;height: 180px;float: left;">
    <%--一定要注意设置enctype="multipart/form-data"--%>
    <form method="post" action="/file/upload" enctype="multipart/form-data">
        <label>单个文件上传</label><hr/>
        <input type="file" name="file"/><hr/>
        <input type="submit" value="上传"/>
    </form>
</div>
<div style="width: 290px;height: 180px;float: left">
    <%--一定要注意设置enctype="multipart/form-data"--%>
    <form method="post" action="/file/upload" enctype="multipart/form-data">
        <label>多个文件上传</label><hr/>
        <%--一定要注意name="file"要与后台传参对应--%>
        <input type="file" name="file"/><br/>
        <input type="file" name="file"/><br/>
        <input type="file" name="file"/><br/>
        <input type="file" name="file"/><br/><hr/>
        <input type="submit" value="上传"/>
    </form>
</div>
</body>
</html>

1.4.result

这里写图片描述
上传结果:
这里写图片描述

2.文件下载

2.1.spring-mvc-servlet.xml

文件下载并没有依赖CommonsMultipartResolver,无需配置。

2.2.FileUtils.java

设置文件下载方式:
1. inline:浏览器内打开此文件(如txt、xml等),不能打开的再下载(如rar等)
2. attachment:下载文件到本地

 /**
     * <p>下载</p>
     * @param fileName 文件名
     * @param suffix 文件后缀
     * @param type 下载方式:inline[浏览器内显示]、attachment[下载]
     * @author hanchao 2018/1/24 22:08
     **/
    @GetMapping("/download/{name}/{suffix}/{type}")
    public void download(HttpServletRequest request,HttpServletResponse response,
                           @PathVariable("name") String fileName,@PathVariable("suffix") String suffix,
                           @PathVariable("type") String type, Model model){
        //获取根目录路径
        File uploadRootDir = new File(request.getServletContext().getRealPath("upload"));
        //获取目标文件
        File file = new File(uploadRootDir.getAbsolutePath() + File.separator + fileName + "." + suffix);
        if (!file.exists()){
            model.addAttribute("returnMessage","文件不存在!");
        }else{
            //获取文件类型
            String mimeType = URLConnection.guessContentTypeFromName(file.getName());
            //如果文件类型为空,则使用默认文件类型
            if (null == mimeType){
                mimeType = "application/octet-stream";
            }
            LOGGER.debug("mimeType:" + mimeType);
            //设置contentType
            response.setContentType(mimeType);
            /*
            设置文件下载方式:
            1.inline:浏览器内打开此文件(如txt、xml等),不能打开的再下载(如rar等)
            2.attachment:下载文件到本地
             */
            response.setHeader("Content-Disposition",type + ";filename=\"" + file.getName() + "\"");
            //设置长度
            response.setContentLength((int) file.length());

            //下载文件
            InputStream inputStream = null;
            try {
                inputStream = new BufferedInputStream(new FileInputStream(file));
                FileCopyUtils.copy(inputStream,response.getOutputStream());
                inputStream.close();
                response.getOutputStream().close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                LOGGER.error("下载文件失败");
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.error("下载文件失败");
            } finally {
                try {
                    inputStream.close();
                    response.getOutputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                    LOGGER.error("下载文件失败");
                }
            }
        }
    }

2.3.file.jsp

<div style="width: 600px;">
    <a href="/file/download/5/jpg/inline">显示5.jpg</a><hr/>
    <a href="/file/download/11/xml/inline">显示11.xml</a><hr/>
    <a href="/file/download/1/txt/inline">显示1.txt</a><hr/>
    <a href="/file/download/5/jpg/attachment">下载5.jpg</a><hr/>
    <a href="/file/download/11/xml/attachment">下载11.xml</a><hr/>
    <a href="/file/download/1/txt/attachment">下载1.txt</a>
</div>

2.4.result

这里写图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值