Spring mvc 下載組件

一、思考java

之前使用J2EE時,都是直接使用Response進行流傳輸下載,如今使用了Spring MVC ,那麼最好是儘可能不要把Spring 的 API 和 J2EE API 混合使用,代碼顯得不友好,尤爲是反感,JSP裏面有Java代碼還有JavaScript代碼。web

二、封裝的代碼spring

package com.hnust.common.controller;

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.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * Created by Heweipo on 2016/5/27.
 * <p>
 * 下載通用控制器,業務類控制器只要繼承該類,調用 export 方法進行下載。
 */
@RestController
public class DownloadController extends BaseController {

    /**
     * 下載文件通用方法
     *
     * @param file 文件對象
     * @return 文件字節流
     */
    public ResponseEntity<byte[]> export(File file) {
        return export(file.getName(), file);
    }


    /**
     * 下載文件通用方法
     *
     * @param fileName 文件名稱
     * @param file     文件對象
     * @return 文件字節流
     */
    public ResponseEntity<byte[]> export(String fileName, File file) {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        headers.setContentDispositionFormData("attachment", encodeFileName(fileName));
        ResponseEntity<byte[]> rs = null;
        try {
            // 這裏不能使用  HttpStatus.CREATED 201 是由於 IE Edge 沒法識別,可是Firefox chrome 沒問題
            rs = new ResponseEntity<>(FileUtils.readFileToByteArray(file),
                    headers, HttpStatus.OK);
        } catch (IOException e) {
            // throw new CommonException(ResponseStatusEnum.FILE_ERROR, e);
        }
        return rs;
    }

    /**
     * 下載文件的名稱,這個是在瀏覽器那裏顯示的名稱
     *
     * @param fileName 文件名稱
     * @return 加碼的文件名稱
     * <p>
     * IE
     * Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
     * <p>
     * Edge
     * Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586
     * <p>
     * Firefox
     * Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
     * <p>
     * Chrome
     * Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
     */
    private String encodeFileName(String fileName) {
        String name = fileName;
        try {
            String agent = request.getHeader("USER-AGENT").toLowerCase();
            if (null != agent && (agent.contains("msie") || agent.contains("edge"))) { // IE edge
                name = URLEncoder.encode(fileName, "UTF-8");
            } else if (agent.contains("safari") || agent.contains("chrome") || agent.contains("firefox")) { // safari chrome firefox
                name = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
            } else { // IE10 IE11
                name = URLEncoder.encode(fileName, "UTF-8");
            }
            // 把加號還原爲空格(IE Edge 有問題)
            name = name.replace("+", "%20");
        } catch (UnsupportedEncodingException e) {
            // throw new CommonException(ResponseStatusEnum.FAILURE, e);
        }
        return name;
    }


}

三、調用組件chrome

@Controller
public class HelloController extends DownloadController {

    /**
     * 
     * 下載組件調用
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public ResponseEntity<byte[]> download() {
        File file = new File("c://1.txt");
        return export(file);
    }

四、注意apache

1)rs = new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);瀏覽器

網上不少人使用這樣的代碼進行下載:app

rs = new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);ide

這樣在Chrome Firefox 瀏覽器中下載沒有問題,可是在IE、Edge就沒法下載,緣由多是IE、Edge沒法識別 201 響應結果。.net

2)下載文件名稱亂碼,或者有+號firefox

這個問題確實很常見了,在IE、Firefox下就必須這樣設置,經過以下瀏覽器頭信息解析加碼方式。 另外,把加號還原爲空格(IE Edge 有問題) ,這個jQuery也是同樣把空格進行encode以後變爲加號了。還原一下

name = name.replace("+", "%20");

相關文章
相關標籤/搜索