SpringMVC的檔案下載功能(附上完整的springmvc的檔案上傳下載示例)
==========================================================
以下使用maven建立檔案上傳下載
============================
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lin</groupId> <artifactId>SpringMVCTest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!-- spring begin --> <!--spring-core--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.0.RELEASE</version> </dependency> <!-- spring-web-mvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.0.RELEASE</version> </dependency> <!-- spring end --> <!-- 檔案上傳下載 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- --> </dependencies> </project>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>SpringTagTest</display-name> <!-- 定義Spring MVC的前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 讓Spring MVC的前端控制器攔截所有請求 --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 編碼過濾器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd"> <!-- 自動掃描該包,SpringMVC會將包下用@Controller註解的類註冊為Spring的controller --> <context:component-scan base-package="com.lin"/> <!-- 設定預設配置方案 --> <mvc:annotation-driven/> <!-- 使用預設的Servlet來響應靜態檔案 --> <mvc:default-servlet-handler/> <!-- 檢視解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 字首 --> <property name="prefix"> <value>/WEB-INF/content/</value> </property> <!-- 字尾 --> <property name="suffix"> <value>.jsp</value> </property> </bean> <!-- 由於SpringMVC上下文中預設沒有裝配 MultipartResolver,因此預設情況下它不能處理檔案上傳工作。 如果想使用spring的檔案上傳功能,則需要在上下文中配置MultipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上傳檔案大小上限,單位為位元組(10MB) --> <property name="maxUploadSize"> <value>10485760</value> </property> <!-- 請求的編碼格式,必須和jsp的pageEncoding屬性一致,以便正確讀取表單的內容,預設為ISO-8859-1 --> <property name="defaultEncoding"> <value>UTF-8</value> </property> </bean> </beans>
MyFile.java
package com.lin.domain;
import org.springframework.web.multipart.MultipartFile;
/**
* 用於接收表單資訊的實體類
*/
public class MyFile {
private String description;
private MultipartFile file;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file = file;
}
}
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>
<!-- 此處要注意的是,在編寫上傳檔案的表單時的編碼型別enctype必須是multipart/form-data ,
method必須設定成post 。只有在這種情況下,瀏覽器才會把使用者選擇的檔案的二進位制資料傳送給伺服器。 -->
<form action="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 colspan="2" align="center"><input type="submit" value="上傳"/></td>
</tr>
</table>
</form>
</body>
FileUploadDownloadController.java
package com.lin.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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.lin.domain.MyFile;
@Controller
public class FileUploadDownloadController {
@RequestMapping(value="/{formName}")
public String loginForm(@PathVariable String formName){
// 動態跳轉頁面
return formName;
}
// /**
// * 以下這個方法只是使用普通的形參來接收表單的引數資訊
// * */
// //上傳檔案會自動繫結到MultipartFile中
// @RequestMapping(value="/upload",method=RequestMethod.POST)
// public String upload(HttpServletRequest request,
// //引數繫結,將表單中名為description和file的引數繫結到形參中(若表單名
// //和形參名相同,則@RequestParam可省略,spring會自動進行引數繫結)
// @RequestParam("description") String description,
// @RequestParam("file") MultipartFile file) throws Exception{
// System.out.println(description);
// //如果檔案不為空,寫入上傳路徑
// if(!file.isEmpty()){
// //上傳檔案路徑
// String path = request.getServletContext().getRealPath("/images/");
// //上傳檔名
// String filename = file.getOriginalFilename();
// //上傳路徑
// File filepath = new File(path,filename);
// //以下輸出的圖片路徑為 D:\eclipseneon3\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\FileUploadTest\images\02.jpg
// //System.out.println(filepath);
// //判斷路徑是否存在,如果不存在就建立一個
// if( !filepath.getParentFile().exists()) {
// filepath.getParentFile().mkdirs();
// }
//
// //將檔案儲存到一個目標檔案中
// file.transferTo(new File(path+File.separator+filename));
// return "success";
// }else{
// return "error";
// }
//
// }
/**
* 以下這個方法使用物件型別的形參來接收表單的引數資訊
* */
//上傳檔案會自動繫結到MultipartFile中
@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request,
//使用物件來接收表單引數
MyFile myFile) throws Exception{
System.out.println(myFile.getDescription());
//如果檔案不為空,寫入上傳路徑
if(!myFile.getFile().isEmpty()){
// //上傳檔案路徑這個是相對於這個eclipse專案的路徑
// String path = request.getServletContext().getRealPath("/images/");
//這是是絕對路徑
String path = "C:\\Users\\wudan\\Desktop";
//上傳檔名
String filename = myFile.getFile().getOriginalFilename();
//上傳路徑
File filepath = new File(path,filename);
//以下輸出的圖片路徑為 D:\eclipseneon3\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\FileUploadTest\images\02.jpg
//System.out.println(filepath);
//判斷路徑是否存在,如果不存在就建立一個
if( !filepath.getParentFile().exists()) {
filepath.getParentFile().mkdirs();
}
//將檔案儲存到一個目標檔案中
myFile.getFile().transferTo(new File(path+File.separator+filename));
return "success";
}else{
return "error";
}
}
/**
* 檔案下載
* download處理方法接收到頁面傳遞的檔名filename後,使用Apache Commons FileUpload
* 元件的FileUtils讀取專案的image資料夾下的該檔案,並將其構建成ResponseEntity物件返回客戶端下載。
*
* 使用ResponseEntity物件,可以很方便的定義返回的HTTPHeaders和HttpStatus。下面程式碼中的
* MediaType,代表的是Internet Media Type,即網際網路媒體型別,也叫做MIME型別。在Http協議訊息頭
* 中,使用Content-Type來表示具體請求中的媒體型別資訊。HTTPStatus型別代表的是Http協議中的狀態。
*/
@RequestMapping(value="/download")
public ResponseEntity<byte[]> download(HttpServletRequest request,@RequestParam("filename")String filename,Model model) throws Exception {
// //下載檔案路徑
// String path = request.getServletContext().getRealPath("/images/");
//這是是絕對路徑
String path = "C:\\Users\\wudan\\Desktop";
File file = new File(path+File.separator+filename);
HttpHeaders headers = new HttpHeaders();
//下載顯示的檔名,解決中文名稱亂碼問題
String downloadFileName = new String(filename.getBytes("UTF-8"),"iso-8859-1");
//通知瀏覽器以attachment(下載方式)開啟圖片
headers.setContentDispositionFormData("attachment", downloadFileName);
//application/octet-stream:二進位制流資料(最常見的檔案下載)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//201 HttpStatus.CREATED
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
}
}
success.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>Insert title here</title>
</head>
<body>
檔案上傳成功!<br>
<a href="download?filename=test11.PDF">示例檔案</a>
</body>
</html>
====================================
================================
以下是原博文程式碼
==============================
檔案下載功能相對簡單些,只需要定義一個超連結即可:<a href="download?filename=示例圖片.jpg">示例圖片</a>
然後在控制器中編寫處理方法:
/**
* 檔案下載
* download處理方法接收到頁面傳遞的檔名filename後,使用Apache Commons FileUpload
* 元件的FileUtils讀取專案的image資料夾下的該檔案,並將其構建成ResponseEntity物件返回客戶端下載。
*
* 使用ResponseEntity物件,可以很方便的定義返回的HTTPHeaders和HttpStatus。下面程式碼中的
* MediaType,代表的是Internet Media Type,即網際網路媒體型別,也叫做MIME型別。在Http協議訊息頭
* 中,使用Content-Type來表示具體請求中的媒體型別資訊。HTTPStatus型別代表的是Http協議中的狀態。
*/
@RequestMapping(value="/download")
public ResponseEntity<byte[]> download(HttpServletRequest request,
@RequestParam("filename")String filename,
Model model) throws Exception {
//下載檔案路徑
String path = request.getServletContext().getRealPath("/images/");
File file = new File(path+File.separator+filename);
HttpHeaders headers = new HttpHeaders();
//下載顯示的檔名,解決中文名稱亂碼問題
String downloadFileName = new String(filename.getBytes("UTF-8"),"iso-8859-1");
//通知瀏覽器以attachment(下載方式)開啟圖片
headers.setContentDispositionFormData("attachment", downloadFileName);
//application/octet-stream:二進位制流資料(最常見的檔案下載)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//201 HttpStatus.CREATED
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);
}
以上就可以使用SpringMVC實現檔案下載的功能。。與上篇上傳部分有個共同的地方是檔案的儲存路徑和讀取的路徑,這裡檔案儲存的路徑在上傳時有指出儲存的位置,這個位置是可以根據自己情況而更改的(雖然我沒有在程式碼中直接給出),,。
還有一個問題是我在測試 檔案下載時遇到的問題:原先下載時我是用360瀏覽器,可以跳出下載頁面,但是不知道為什麼下載不下來;後來換成谷歌瀏覽器就可以直接下載成功。。