Spring4 MVC檔案下載範例


這篇文章將向您展示如何使用Spring MVC4執行檔案下載,我們將看到應用程式從檔案系統內部以及外部檔案下載檔案。


本教學的主要亮點:

下載檔案是相當簡單的,涉及以下步驟。

  • 建立一個InputStream到檔案用於下載。
  • 查詢MIME型別下載檔案的內容。
    –可以是application/pdf, text/html,application/xml,image/png等等。
  • 將內容型別與上述發現的MIME型別響應(HttpServletResponse)。
    response.setContentType(mimeType);
  • 針對以上找到MIME型別設定內容長度。
    response.setContentLength(file.getLength());//length in bytes
  • 為響應設定內容處理檔頭。
    response.setHeader(「Content-Disposition」, 「attachment; filename=」 + fileName); //隨著「附件」檔案將下載。可能會顯示一個「另存為」基於瀏覽器的設定對話方塊。

    response.setHeader(「Content-Disposition」, 「inline; filename=」 + fileName);//通過「內聯」瀏覽器將嘗試顯示內容到瀏覽器中(圖片,PDF,文字,...)。對於其他內容型別,檔案將直接下載。

  • 從InputStream中複製位元組響應到 OutputStream。
  • 一旦複製完成後,關閉輸入輸出流。

完整實施例在下面討論。


使用到以下技術:

  • Spring 4.2.0.RELEASE
  • Bootstrap v3.3.2
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2

現在讓我們開始

專案結構

在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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.yiibai.springmvc</groupId>
  <artifactId>Spring4MVCFileDownloadExample</artifactId>
  <packaging>war</packaging>
  <version>1.0.0</version>
  <name>Spring4MVCFileDownloadExample Maven Webapp</name>
 
     <properties>
		<springframework.version>4.2.0.RELEASE</springframework.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	</dependencies>


	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.4</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<warName>Spring4MVCFileDownloadExample</warName>
						<failOnMissingWebXml>false</failOnMissingWebXml>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>

		<finalName>Spring4MVCFileDownloadExample</finalName>
	</build>
</project>
 

建立控制器

package com.yiibai.springmvc.controller;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLConnection;
import java.nio.charset.Charset;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class FileDownloadController {
	
	private static final String INTERNAL_FILE="irregular-verbs-list.pdf";
	private static final String EXTERNAL_FILE_PATH="C:/mytemp/SpringMVCHibernateManyToManyCRUDExample.zip";
	

	@RequestMapping(value={"/","/welcome"}, method = RequestMethod.GET)
	public String getHomePage(ModelMap model) {
		return "welcome";
	}

	/*
	 * Download a file from 
	 *   - inside project, located in resources folder.
	 *   - outside project, located in File system somewhere. 
	 */
	@RequestMapping(value="/download/{type}", method = RequestMethod.GET)
	public void downloadFile(HttpServletResponse response, @PathVariable("type") String type) throws IOException {
	
		File file = null;
		
		if(type.equalsIgnoreCase("internal")){
			ClassLoader classloader = Thread.currentThread().getContextClassLoader();
			file = new File(classloader.getResource(INTERNAL_FILE).getFile());
		}else{
			file = new File(EXTERNAL_FILE_PATH);
		}
		
		if(!file.exists()){
			String errorMessage = "Sorry. The file you are looking for does not exist";
			System.out.println(errorMessage);
			OutputStream outputStream = response.getOutputStream();
			outputStream.write(errorMessage.getBytes(Charset.forName("UTF-8")));
			outputStream.close();
			return;
		}
		
		String mimeType= URLConnection.guessContentTypeFromName(file.getName());
		if(mimeType==null){
			System.out.println("mimetype is not detectable, will take default");
			mimeType = "application/octet-stream";
		}
		
		System.out.println("mimetype : "+mimeType);
		
        response.setContentType(mimeType);
        
        /* "Content-Disposition : inline" will show viewable types [like images/text/pdf/anything viewable by browser] right on browser 
            while others(zip e.g) will be directly downloaded [may provide save as popup, based on your browser setting.]*/
        response.setHeader("Content-Disposition", String.format("inline; filename=\"" + file.getName() +"\""));

        
        /* "Content-Disposition : attachment" will be directly download, may provide save as popup, based on your browser setting*/
        //response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
        
        response.setContentLength((int)file.length());

		InputStream inputStream = new BufferedInputStream(new FileInputStream(file));

        //Copy bytes from source to destination(outputstream in this example), closes both streams.
        FileCopyUtils.copy(inputStream, response.getOutputStream());
	}

}

該控制器包括兩個檔案。一個檔案是內部應用(內部資源),和其他檔案位於外部的應用程式的檔案系統。您的專案一定要改變外部檔案的路徑。僅用於演示的目的,我們已在路徑一個額外的路徑變數(內部/外部)。我們正在使用Spring FileCopyUtils工具類流從源複製到目的地。

組態

package com.yiibai.springmvc.configuration;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.yiibai.springmvc")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{

	
	@Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        registry.viewResolver(viewResolver);
    }
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }

}

初始化

package com.yiibai.springmvc.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { HelloWorldConfiguration.class };
    }
  
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
 
 }

新增檢視

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>Spring 4 MVC File Download Example</title>
	<link href="<c:url value='/static/css/bootstrap.css' />"  rel="stylesheet"></link>
	<link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
</head>
<body>
	<div class="form-container">
		<h1>Welcome to FileDownloader Example</h1>
		
		Click on below links to see FileDownload in action.<br/><br/>
		
		
		<a href="<c:url value='/download/internal' />">Download This File (located inside project)</a>  
		<br/>
		<a href="<c:url value='/download/external' />">Download This File (located outside project, on file system)</a>
		
	</div> 
</body>
</html>

構建,部署和執行應用程式

現在構建war(在前面的Eclipse教學)或通過Maven的命令列( mvn clean install)。部署 war 到Servlet3.0容器。或:

開啟瀏覽器,瀏覽 http://localhost:8080/Spring4MVCFileDownloadExample

點選第二個連結。外部檔案應被下載。

點選第一個連結。內部檔案[這是一個PDF]應該顯示在瀏覽器中,這是由於 Content-Disposition: inline. 通過內聯,如果內容可以通過瀏覽器顯示,它會顯示它在瀏覽器中。

現在從內聯更改內容處置備註。構建並部署。點選第一個連結。這個時候您應該看到 PDF檔案被下載。

就這樣,完成!

下載程式碼:http://pan.baidu.com/s/1c1lmeL6