1. 程式人生 > >SpringMVC的檔案下載功能(附上完整的springmvc的檔案上傳下載示例)

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瀏覽器,可以跳出下載頁面,但是不知道為什麼下載不下來;後來換成谷歌瀏覽器就可以直接下載成功。。