天天看點

Spring MVC 實作檔案的上傳和下載下傳 (八)目錄

 完整的項目案例: springmvc.zip

目錄

Spring MVC 實作檔案的上傳和下載下傳 (八)目錄

SpringMVC 中,檔案的上傳,是通過 MultipartResolver 實作的。 是以,如果要實作檔案的上傳,隻要在 spring-mvc.xml 中注冊相應的 MultipartResolver 即可。

MultipartResolver 的實作類有兩個:

  1. CommonsMultipartResolver
  2. StandardServletMultipartResolver

兩個的差別:

  1. 第一個需要使用 Apache 的 commons-fileupload 等 jar 包支援,但它能在比較舊的 servlet 版本中使用。
  2. 第二個不需要第三方 jar 包支援,它使用 servlet 内置的上傳功能,但是隻能在 Servlet 3 以上的版本使用。

第一個使用步驟:

/*CommonsMultipartResolver  上傳用到的兩個包*/

"commons-fileupload:commons-fileupload:1.3.1",

"commons-io:commons-io:2.4"      

如果是maven項目的話直接導入:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

dispatcher-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="edu.nf.ch08.controller"/>

    <mvc:annotation-driven/>

    <mvc:default-servlet-handler/>
    <!-- 檔案上傳有兩種方式,一種基于Servlet3.0的上傳,一種基于
     commons-upload上傳,如果使用Servlet3.0的上傳方式,可以
     不需要配置MultipartResolver,Spring預設會注冊一個
     StandardServletMultipartResolver。隻需要在web.xml中
     啟用<multipart-config>。
     如果想使用commons-upload,那麼需要配置一個CommonsMultipartResolver,
     且指定bean的id為multipartResolver-->
    <!-- 這裡使用commons-upload-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 限制檔案上傳的總大小(機關:位元組),不配置此屬性預設不限制 -->
        <property name="maxUploadSize" value="104857600"/>
        <!-- 設定檔案上傳的預設編碼-->
        <property name="defaultEncoding" value="utf-8"/>
    </bean>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>      

 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- 請求總控器 -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>      

背景java(上傳、下載下傳)處理代碼:

package edu.nf.ch08.controller;

import org.apache.commons.io.FileUtils;
import org.springframework.core.io.InputStreamResource;
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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;

/**
 * @author wangl
 * @date 2018/11/2
 */
@Controller
public class UploadController {

    /**
     * 檔案上傳隻需要Spring傳入一個MultipartFile對象即可,
     * 這個對象可以擷取檔案相關上傳的資訊。
     * 一個MultipartFile表示單個檔案上傳,當需要上傳多個檔案時
     * 隻需要聲明為MultipartFile[]數組即可。
     * @return
     */
    @PostMapping("/upload")
    public ModelAndView upload(MultipartFile file){
        //擷取目前系統使用者目錄
        String home = System.getProperty("user.home");
        //指定上傳的檔案夾目錄
        File uploadDir = new File(home + "/files");
        //如果目錄不存在,則建立
        if(!uploadDir.exists()){
            uploadDir.mkdir();
        }
        //擷取上傳的檔案名
        String fileName = file.getOriginalFilename();
        //建構一個完整的檔案上傳對象
        File uploadFile = new File(uploadDir.getAbsolutePath() + "/" + fileName);
        try {
            //通過transferTo方法進行上傳
            file.transferTo(uploadFile);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        //将檔案名存入Model,轉發到index頁面
        ModelAndView mv = new ModelAndView("index");
        mv.addObject("fileName", fileName);
        return mv;
    }

    /**
     * 檔案下載下傳1
     * 讀取伺服器本地檔案并封裝為ResponseEntity對象
     * 響應用戶端,ResponseEntity封裝一個位元組數組。
     *
     * 注意:如果檔案很大,那麼讀入記憶體的位元組數組就會很大,這時很容易引起記憶體溢出。
     * 是以,這種方法不太适合下載下傳大檔案使用
     * @param fileName 檔案名
     * @return
     */
    @GetMapping("/download")
    public ResponseEntity<byte[]> download(String fileName){
        //依據檔案名建構本地檔案路徑
        String filePath = System.getProperty("user.home") + "/files/" + fileName;
        //依據檔案路徑建構File對象
        File file = new File(filePath);
        //建立響應頭對象,設定響應資訊
        HttpHeaders headers = new HttpHeaders();
        try {
            //對檔案名進行重新編碼,防止在響應頭中出現中文亂碼
            String headerFileName = URLEncoder.encode(fileName,"UTF-8");
            //設定響應内容處理方式為附件,并指定檔案名
            headers.setContentDispositionFormData("attachment", headerFileName);
            //設定響應頭類型為application/octet-stream,表示是一個流類型
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            //将檔案轉換成位元組數組
            byte[] bytes = FileUtils.readFileToByteArray(file);
            //建立ResponseEntity對象(封裝檔案位元組數組、響應頭、響應狀态碼)
            ResponseEntity<byte[]> entity = new ResponseEntity<>(bytes, headers, HttpStatus.CREATED);
            //最後将整個ResponseEntity對象傳回給DispatcherServlet
            return entity;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("檔案下載下傳失敗");
        }
    }

    /**
     * 檔案下載下傳2(主要解決下載下傳大檔案)
     * 讀取伺服器本地檔案并封裝為ResponseEntity對象
     * 響應用戶端,ResponseEntity封裝一個InputStreamResource
     * @param fileName 檔案名
     * @return
     */
    @GetMapping("/download2")
    public ResponseEntity<InputStreamResource> download2(String fileName){
        //依據檔案名建構本地檔案路徑
        String filePath = System.getProperty("user.home") + "/files/" + fileName;
        //依據檔案路徑建構File對象
        File file = new File(filePath);
        //建立響應頭對象,設定響應資訊
        HttpHeaders headers = new HttpHeaders();
        try {
            //對檔案名進行重新編碼,防止在響應頭中出現中文亂碼
            String headerFileName = URLEncoder.encode(fileName,"UTF-8");
            //設定響應内容處理方式為附件,并指定檔案名
            headers.setContentDispositionFormData("attachment", headerFileName);
            //設定響應頭類型為application/octet-stream,表示是一個流類型
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            //打開一個輸入流
            InputStream inputStream = FileUtils.openInputStream(file);
            //建立InputStreamResource封裝輸入流對象,用于讀取伺服器檔案
            InputStreamResource resource = new InputStreamResource(inputStream);
            //建立ResponseEntity對象(InputStreamResource、響應頭、響應狀态碼)
            ResponseEntity<InputStreamResource> entity = new ResponseEntity<>(resource, headers, HttpStatus.CREATED);
            //最後将整個ResponseEntity對象傳回給DispatcherServlet
            return entity;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("檔案下載下傳失敗");
        }
    }
}      

上傳檔案的網頁html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>檔案上傳</h1>
<!-- 當有檔案上傳時,表單的enctype必須設定為multipart/form-data -->
<form method="post" action="upload" enctype="multipart/form-data">
    File:<input type="file" name="file"/><br/>
    <input type="submit" value="submit"/>
</form>
</body>
</html>

      
Spring MVC 實作檔案的上傳和下載下傳 (八)目錄

上傳成功後轉發的jsp(下載下傳檔案)頁面:

<%--
  Created by IntelliJ IDEA.
  User: wangl
  Date: 2018/11/2
  Time: 09:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<a href="download2?fileName=${fileName}">${fileName}</a>
</body>
</html>      
Spring MVC 實作檔案的上傳和下載下傳 (八)目錄

項目結構:

Spring MVC 實作檔案的上傳和下載下傳 (八)目錄

轉載于:https://www.cnblogs.com/hhmm99/p/9896531.html