0062 Spring MVC的文件上傳與下載--MultipartFile--ResponseEntity

文件上傳功能在網頁中見的太多了,好比上傳照片做爲頭像、上傳Excel文檔導入數據等html

先寫個上傳文件的htmljava

<!DOCTYPE html>
<html>
<head>
    <title>Spring MVC文件上傳與下載</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   
</head>
    <body>
        <form action="upload" method="POST" enctype="multipart/form-data">   <!-- 上傳文件注意enctype -->
            文件描述:<input type="text" name="desc" /> <br><br>
            選擇文件:<input type="file" name="file" /> <br><br>
            <input type="submit" value="上傳" /> 
        </form>
    </body>
</html>

寫個controller接收上傳的文件web

package net.sonng.mvcdemo.controller;

import java.io.File;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class UploadController {
    @RequestMapping("/upload")
    public String upload(HttpServletRequest request,@RequestParam("desc") String desc,@RequestParam("file") MultipartFile file) throws Exception{
        //接收到的文件綁定到MultipartFile對象中
        System.out.println(desc);
        if (!file.isEmpty()){  //若是文件不爲空,那麼將它存起來
            String path=request.getServletContext().getRealPath("/images");  //接收的文件放在/images目錄下,並得到文件系統目錄
            String filename=file.getOriginalFilename();//獲取文件名
            File filepath=new File(path,filename);     //根據文件所在目錄和文件名建立File對象
            if(!filepath.getParentFile().exists()){    //若是所在目錄不存在,那麼建立
                filepath.getParentFile().mkdirs();
            }
            file.transferTo(new File(path+File.separator+filename)); //調用transferTo()方法將文件存儲到目標位置
            //file.transferTo(filepath)                              //也能夠用這條語句
            return "result";
        }else{
            return "error";
        }
    }
}

關於multipartFile

經常使用方法有:spring

  • String getContentType(): 獲取文件的MIME類型
  • String getOriginalFilename(): 獲取文件名
  • long getSize(): 獲取文件大小,單位KB
  • boolean isEmpty(): 文件是否爲空
  • void transferTo(File dest): 將文件存儲到dest
  • String getName(): 獲取表單的參數名
  • byte[] getBytes(): 獲取文件數據
  • InputStream getInputStream(): 獲取文件流

Spring MVC的文件上傳組件須要MultipartResolver接口,依賴於Apache Commons FileUpload技術實現了一個實現類CommonsMultipartResolver,所以還須要兩方面的工做:1. 引入Apache Commons FileUpload包;2. 配置xmlapache

引入Apache Commons FileUpload及其依賴的Commons IO瀏覽器

配置xmlmvc

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize">    <!-- 還能夠限制上傳文件的大小 -->
            <value>10485760</value>
        </property>
        <property name="defaultEncoding" >  <!-- 注意這個編碼格式,要跟上傳的頁面的編碼一致 -->
            <value>UTF-8</value>
        </property>
    </bean>

部署訪問,檢查Tomcat的該app目錄下的/images目錄下是否有上傳的文件。app

將上傳的文件以對象屬性的形式保存

好比頭像,老是屬於某個用戶,所以在用戶類中能夠定義一個MultipartFile屬性存儲用戶頭像
上傳用戶頭像的htmljsp

<!DOCTYPE html>
<html>
<head>
    <title>Spring MVC文件上傳與下載</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
    <body>
        <form action="upload" method="POST" enctype="multipart/form-data">
            用戶名:<input type="text" name="username" /> <br><br>
            選擇圖片:<input type="file" name="avatar" /> <br><br>
            <input type="submit" value="上傳" /> 
        </form>
    </body>
</html>

實體類user:測試

package net.sonng.mvcdemo.entity;

import org.springframework.web.multipart.MultipartFile;

public class User {
    private String username;
    private MultipartFile avatar;   //上傳的頭像做爲User的一個屬性
    //。。。。。  
}

寫controller:

package net.sonng.mvcdemo.controller;

import java.io.File;

import javax.servlet.http.HttpServletRequest;

import net.sonng.mvcdemo.entity.User;

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.RequestParam;

@Controller
public class UploadController {
    @RequestMapping("/upload")
    public String upload(HttpServletRequest request,@ModelAttribute User user,Model model) throws Exception{
        if (!user.getAvatar().isEmpty()){
            String path=request.getServletContext().getRealPath("/avatars/");
            String filename=user.getAvatar().getOriginalFilename();
            File filepath=new File(path,filename);
            if(!filepath.getParentFile().exists()){
                filepath.getParentFile().mkdirs();
            }
            user.getAvatar().transferTo(new File(path+File.separator+filename));
            model.addAttribute("user", user);
            return "result";
        }else{
            return "error";
        }
    }
    @RequestMapping("/download")  //上傳了以後再下載
    public ResponseEntity<byte[]> download(HttpServletRequest request,@RequestParam("filename") String filename,Model model)throws Exception{
        String path=request.getServletContext().getRealPath("/avatars/");  //獲取文件所在路徑
        filename=new String(filename.getBytes("ISO-8859-1"),"UTF-8");     //不知何故,result.jsp的請求參數是ISO-8859-1編碼的,但明明設置了charset=utf-8
        File file=new File(path+File.separator+filename);
        HttpHeaders headers=new HttpHeaders();
        String downloadFileName=new String(filename.getBytes("UTF-8"),"ISO-8859-1");  //少了這句,可能致使下載中文文件名的文檔,只有後綴名的狀況
        headers.setContentDispositionFormData("attachment", downloadFileName);//告知瀏覽器如下載方式打開
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//設置MIME類型
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);//
        //用FileUpload組件的FileUtils讀取文件,並構建成ResponseEntity<byte[]>返回給瀏覽器
        //HttpStatus.CREATED是HTTP的狀態碼201
    }
}

上傳成功後,返回頁面result.jsp,

<%@page pageEncoding="utf-8" 
        contentType="text/html;charset=utf-8" %>
<html>
    <head>
        <title>文件的上傳與下載</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
        <p>下載剛纔上傳的文件</p>
        <a href="download?filename=${user.avatar.originalFilename }">下載文件</a>
    </body>
</html>

部署測試,分別測試中文/英文文件名

總結

上傳文件:上傳的文件綁定到MultipartFile中;獲取文件名;要存儲的文件系統路徑;建立目錄;用MultipartFile的transferTo()存儲 下載文件:獲取要下載的文件名,注意編碼;在HttpHeaders中設置如下載方式打開,設置MIME類型;用FileUtils.readFileToByteArray()讀取文件數據;用ResponseEntity<byte[]>構建返回對象

相關文章
相關標籤/搜索