天天看點

Spring MVC代碼執行個體系列-10:Spring MVC實作簡單的檔案上傳和下載下傳

超級通道 :Spring MVC代碼執行個體系列-緒論

本章主要記錄Spring MVC實作簡單的檔案上傳和下載下傳。涉及到的知識點有:

-

CommonsMultipartResolver

:通用多部件解析器,用來實作多檔案上傳

-

MultipartFile

:多部件檔案,用來傳輸多種類型的檔案

- 兩種檔案儲存方式:1.通過

BufferedOutputStream

寫入伺服器。2.通過MultipartFile封裝的方法寫入。

- 兩種檔案下載下傳方式:通過設定

Content-Disposition

inline

attachment

試下浏覽器顯示和檔案下載下傳。

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 = ; i < files.length; i++) {
            MultipartFile file = files[i];
            //如果檔案大于200kb,則不能上傳
            if (file.getSize() > ){
                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() > ){
            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: //
  Time: :
  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: px px;text-align:center; border:px 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

Spring MVC代碼執行個體系列-10:Spring MVC實作簡單的檔案上傳和下載下傳

上傳結果:

Spring MVC代碼執行個體系列-10:Spring MVC實作簡單的檔案上傳和下載下傳

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

Spring MVC代碼執行個體系列-10:Spring MVC實作簡單的檔案上傳和下載下傳

繼續閱讀