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

現在讓我們開始

項目結構

Spring4

在pom.xml中聲明依賴關係


4.0.0
com.yiibai.springmvc
Spring4MVCFileDownloadExample
war
1.0.0
Spring4MVCFileDownloadExample Maven Webapp

 <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>

創建控制器

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" %>

Spring 4 MVC File Download Example

Welcome to FileDownloader Example

    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> 

構建,部署和運行應用程序

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

打開瀏覽器,瀏覽 http://localhost:8080/Spring4MVCFileDownloadExample
Spring4

點擊第二個鏈接。外部文件應被下載。
Spring4

點擊第一個鏈接。內部文件[這是一個PDF]應該顯示在瀏覽器中,這是由於 Content-Disposition: inline. 通過內聯,如果內容可以通過瀏覽器顯示,它會顯示它在瀏覽器中。
Spring4

現在從內聯更改內容處置備註。構建並部署。點擊第一個鏈接。這個時候您應該看到 PDF文件被下載。
Spring4

就這樣,完成!

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