Spring Web MVC框架(五) 文件上傳

Spring同樣支持文件上傳功能,不過該功能默認未開啟,因為可能有些開發者可能希望自己處理文件上傳過程。Spring的文件上傳功能在org.springframework.web.multipart包下,有兩個MultipartResolver實現用來支持文件上傳功能,一個是基于Commons FileUpload ,另一個基于Servlet 3.0 multipart請求解析功能。這兩個MultipartResolver差不多,一個需要添加Commons FileUpload的依賴,另一個需要在Servlet 3.0容器上運行。大家可以根據需要選擇。

定義MultipartResolver

使用Commons FileUpload MultipartResolver

在配置文件中添加如下一段,我們可以在Bean定義中配置上傳文件大小等屬性。

<bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="100000"/>

</bean>

使用Servlet 3.0 MultipartResolver

由于使用的是Servlet API提供的文件上傳功能,所以文件大小等配置需要在web.xml中進行配置。我們需要在dispathcer-servlet中添加<multipart-config>標簽,它有四個子標簽來設置文件上傳的屬性。

這四個屬性如下:

  • location ,臨時文件的存放位置,這個路徑必須是絕對路徑。
  • fileSizeThreshold,文件起始值,大于該值文件才會被臨時保存,單位是字節。
  • MaxFileSize,單個文件的最大值,單位是字節,不管上傳幾個文件,只要有一個文件大小超過該值就會拋出IllegalStateException。
  • maxRequestSize,文件上傳請求的最大值,單位是字節,主要作用是當上傳多個文件是配置整個請求的大小,當超出該值是拋出IllegalStateException。
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
    <multipart-config>
        <max-file-size>100000</max-file-size>
    </multipart-config>
</servlet>

然后我們在Spring配置文件中添加Servlet 3.0 MultipartResolver。

<bean id="multipartResolver"
        class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

獲取文件

配置好了Multipart解析器之后,我們就可以接收文件了。首先定義一個頁面fileupload.jsp,用于上傳文件并顯示服務器中的文件。注意在表單中我們必須添加enctype="multipart/form-data"才能正確的上傳文件。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上傳</title>
    <meta charset="utf-8">

</head>
<body>
<h2>文件上傳</h2>
<form action="<c:url value="/fileupload"/>"
      method="post" enctype="multipart/form-data">
    <label for="file">文件</label>
    <input type="file" name="file" id="file"/>
    <br>
    <input type="submit" value="提交">
</form>

<h2>文件下載</h2>

<c:forEach var="file" items="${files}">
    <a href="<c:url value="/findFile?filename=${file}"/>">${file}</a>
    <br>
</c:forEach>

</body>
</html>

然后就可以在控制器中獲取文件了。由于MultipartFile和它對應的臨時文件會在方法結束之后被Spring清除,所以我們必須在方法中將文件保存到合適的地方。這里我定義了一個UserFile類將文件保存到Session中。

public class UserFile {
    private String filename;
    private byte[] bytes;
}

然后就是控制器了。在請求方法中,我們可以像普通參數那樣獲取上傳的文件,只不過文件對應的類型是MultipartFile,如果使用的是Servlet 3.0標準的,那么類型還可以是javax.servlet.http.Part。我寫了兩個處理方法,第一個將MultipartFile轉化為上面的類型,然后保存到Session中。第二個方法用于獲取Session中的文件。

@Controller
public class FileUploadController {
    @RequestMapping("/fileupload")
    public String fileUpload(HttpSession session, @RequestParam(required = false) MultipartFile file, Model model) throws IOException {
        List<UserFile> files = (List<UserFile>) session.getAttribute("files");
        if (files == null)
            files = new ArrayList<>();
        if (file != null) {
            UserFile f = new UserFile();
            f.setFilename(file.getOriginalFilename());
            f.setBytes(file.getBytes());
            files.add(f);
        }
        session.setAttribute("files", files);
        List<String> filenames = files.stream()
                .map(UserFile::getFilename)
                .collect(Collectors.toList());
        model.addAttribute("files", filenames);

        return "fileupload";
    }

    @RequestMapping("/findFile")
    public void findFile(HttpSession session, @RequestParam String filename, HttpServletResponse response) throws IOException {
        List<UserFile> files = (List<UserFile>) session.getAttribute("files");
        Optional<UserFile> file = files.stream()
                .filter(o -> Objects.equals(o.getFilename(), filename))
                .findFirst();
        OutputStream out = response.getOutputStream();
        out.write(file.get().getBytes());
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容