1. 程式人生 > >SpringMVC 文件上傳下載

SpringMVC 文件上傳下載

文章 med ack ava 註冊 nload 服務器 formdata 方法

文件上傳

文件上傳是項目開發中最常見的功能。為了能上傳文件,必須將表單的method設置為POST,並將enctype設置為multipart/form-data。只有在這樣的情況下,瀏覽器才會把用戶選擇的文件以二進制數據發送給服務器。

一旦設置了enctype為multipart/form-data,瀏覽器即會采用二進制流的方式來處理表單數據,而對於文件上傳的處理則涉及在服務器端解析原始的HTTP響應。在2003年,Apache Software Foundation發布了開源的Commons FileUpload組件,其很快成為Servlet/JSP程序員上傳文件的最佳選擇。

Servlet3.0規範已經提供方法來處理文件上傳,但這種上傳需要在Servlet中完成。而Spring MVC則提供了更簡單的封裝。
Spring MVC為文件上傳提供了直接的支持,這種支持是用即插即用的MultipartResolver實現的。Spring MVC使用Apache Commons FileUpload技術實現了一個MultipartResolver實現類:CommonsMultipartResolver。因此,SpringMVC的文件上傳還需要依賴Apache Commons FileUpload的組件。

MultipartFile對象

Spring MVC會將上傳的文件綁定到MultipartFile對象中。MultipartFile提供了獲取上傳文件內容、文件名等方法。通過transferTo()方法還可以將文件存儲到硬件中,MultipartFile對象中的常用方法如下:

  • byte[] getBytes():獲取文件數據
  • String getContentType[]:獲取文件MIME類型,如image/jpeg等
  • InputStream getInputStream():獲取文件流
  • String getName():獲取表單中文件組件的名字
  • String getOriginalFilename():獲取上傳文件的原名
  • Long getSize():獲取文件的字節大小,單位為byte
  • boolean isEmpty():是否有上傳文件
  • void transferTo(File dest):將上傳文件保存到一個目錄文件中

文件下載

在頁面給出了一個超鏈接,該鏈接href的屬性等於要下載文件的文件名,就可以實現文件下載了。

接收頁面傳遞的文件名filename後,使用Apache Commons FileUpload組件的FileUtils讀取項目的上傳文件,並將其構建成ResponseEntity對象返回客戶端下載。

使用ResponseEntity對象,可以很方便的定義返回的HttpHeaders和HttpStatus。上面代碼中的MediaType,代表的是Internet Media Type,即互聯網媒體類型,也叫做MIME類型。在Http協議消息頭中,使用Content-Type來表示具體請求中的媒體類型信息。HttpStatus類型代表的是Http協議中的狀態。有關MediaType和HttpStatus類可以參考Spring MVC的API文檔。

pom.xml增加

<!-- 文件上傳組件 -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3</version>
</dependency>

創建uploadForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上傳</title>
</head>
<body>
    <h2>文件上傳</h2>
    <form action="${pageContext.request.contextPath}/mvc/upload" enctype="multipart/form-data" method="post">
        <table>
            <tr>
                <td>文件描述:</td>
                <td><input type="text" name="description"></td>
            </tr>
            <tr>
                <td>請選擇文件:</td>
                <td><input type="file" name="file"></td>
            </tr>
            <tr>
                <td><input type="submit" value="上傳"></td>
            </tr>
        </table>
    </form>
</body>
</html>

創建uploadForm2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用戶註冊</title>
</head>
<body>
    <h2>用戶註冊</h2>
    <form action="${pageContext.request.contextPath}/mvc/upload2" enctype="multipart/form-data" method="post">
        <table>
            <tr>
                <td>用戶名:</td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td>請上傳頭像:</td>
                <td><input type="file" name="image"></td>
            </tr>
            <tr>
                <td><input type="submit" value="註冊"></td>
            </tr>
        </table>
    </form>
</body>
</html>

創建userInfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件下載</title>
</head>
<body>
    <h3>文件下載</h3>
    <a href="download?filename=${requestScope.user.image.originalFilename}"> ${requestScope.user.image.originalFilename }
    </a>
</body>
</html>

springmvc-servlet.xml添加

SpringMVC上下文中默認沒有裝配MultipartResolver,因此默認情況下其不能處理文件上傳工作。如果想使用Spring的文件上傳功能,則需要在上下文中配置MultipartResolver

<!-- 文件上傳的配置 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="1048576" /><!-- 上傳文件大小上限,單位為字節(1MB) -->
    <property name="defaultEncoding" value="UTF-8" /><!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,默認為ISO-8859-1 -->
</bean>

創建User2.java對象

使用對象接受接收上傳文件,必須要實現序列化接口

package com.xc.entity;

import java.io.Serializable;

import org.springframework.web.multipart.MultipartFile;

public class User2 implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private MultipartFile image;

    public User2() {
        super();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public MultipartFile getImage() {
        return image;
    }

    public void setImage(MultipartFile image) {
        this.image = image;
    }

}

創建UploadController.java

package com.xc.controller;

import java.io.File;

import javax.servlet.http.HttpServletRequest;

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.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.xc.entity.User2;

@Controller
@RequestMapping("/mvc")
public class UploadController {

    // 上傳文件會自動綁定到MultipartFile中
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String upload(HttpServletRequest request, @RequestParam("description") String description,
            @RequestParam("file") MultipartFile multipartFile) throws Exception {

        System.out.println(description);
        if (!multipartFile.isEmpty()) {// 是否有上傳文件
            // 上傳文件路徑
            // String path = request.getServletContext().getRealPath("/upload/");
            // 得到上傳文件的保存目錄,將上傳的文件存放於WEB-INF目錄下,不允許外界直接訪問,保證上傳文件的安全
            String path = request.getServletContext().getRealPath("/WEB-INF/upload");
            System.out.println(path);
            String filename = multipartFile.getOriginalFilename();// 獲取上傳文件的原名
            File filepath = new File(path, filename);
            System.out.println(filepath);
            // 判斷路徑是否存在,如果不存在就創建一個
            if (!filepath.getParentFile().exists()) {
                filepath.getParentFile().mkdirs();
            }
            multipartFile.transferTo(new File(path + File.separator + filename));// 將上傳文件保存到一個目標文件當中
            return "success";
        } else {
            return "error";
        }
    }

    @RequestMapping(value = "/upload2")
    public String register(HttpServletRequest request, @ModelAttribute User2 user, Model model) throws Exception {
        System.out.println(user.getName());
        // 如果文件不為空,寫入上傳路徑
        if (!user.getImage().isEmpty()) {
            // 上傳文件路徑
            String path = request.getServletContext().getRealPath("/WEB-INF/upload");
            // 上傳文件名
            String filename = user.getImage().getOriginalFilename();
            File filepath = new File(path, filename);
            // 判斷路徑是否存在,如果不存在就創建一個
            if (!filepath.getParentFile().exists()) {
                filepath.getParentFile().mkdirs();
            }
            // 將上傳文件保存到一個目標文件當中
            user.getImage().transferTo(new File(path + File.separator + filename));
            // 將用戶添加到model
            model.addAttribute("user", user);
            return "userInfo";
        } else {
            return "error";
        }
    }

    @RequestMapping(value = "/download")
    public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, Model model) throws Exception {
        // 下載文件路徑
        String path = request.getServletContext().getRealPath("/WEB-INF/upload/");
        File file = new File(path + File.separator + filename);
        HttpHeaders headers = new HttpHeaders();
        // 下載顯示的文件名,解決中文名稱亂碼問題
        String downloadFielName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
        // 通知瀏覽器以attachment(下載方式)打開圖片
        headers.setContentDispositionFormData("attachment", downloadFielName);
        // application/octet-stream : 二進制流數據(最常見的文件下載)。
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
    }

}

參考文章:
Spring MVC 實現文件的上傳和下載

SpringMVC 文件上傳下載