Spring Boot下载踩坑实录,以及如何正确的下载服务器的资源到本地

核心代码


import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * @program: svc
 * @description:
 * @author: tangweiming
 * @create: 2019/6/30 14:08
 */
public class FileDownloadUtil {

    /**
     * 下载文件
     * @param originalFileName :下载文件的原始文件名
     * @param file             :下载的文件
     * @param response         :相应对象
     */
    public static void downloadFile(String originalFileName, File file, HttpServletResponse response, HttpServletRequest request) {
        // 数据校验
        checkParam(originalFileName,file);

        //相应头的处理
        //清空response中的输出流
        response.reset();
        //设置文件大小
        response.setContentLength((int) file.length());

        //设置Content-Type头
        response.setContentType("application/force-download");// 设置强制下载不打开       
        try {
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" +  URLEncoder.encode(originalFileName, "UTF-8"));// 设置文件名
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //将来文件流写入response中
        FileInputStream fileInputStream = null;
        ServletOutputStream outputStream = null;
        try {
            //获取文件输入流
            fileInputStream = new FileInputStream(file);
            //创建数据缓冲区
            byte[] buffers = new byte[1024];

            //通过response中获取ServletOutputStream输出流
            outputStream = response.getOutputStream();
            int length;

            while ((length = fileInputStream.read(buffers)) > 0) {
                //写入到输出流中
                outputStream.write(buffers, 0, length);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //流的关闭
            if(fileInputStream != null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 下载文件的参数的校验,如果参数不合法则抛出自定义异常
     * @param originalFileName :文件原始文件名
     * @param file :待下载的文件
     */
    private static void checkParam(String originalFileName, File file) {
        if(StringUtils.isBlank(originalFileName)){
            throw new BusinessException("输入的文件原始文件名为空");
        }
        if(file == null || !file.exists() ){
            throw new BusinessException("待在下载的文件不存在!");
        }
    }

  
}

 

下载时候会遇到的坑:

1.文件名为中文,为了方便我这边直接将文件名设置为了中文,但是可能有些人因为必要,需要下载时的文件名包含中文,这边给提供一段代码,代码都是参考网上的,很感谢提供帮助的大佬.

/**
     * 获取URL编码后的原始文件名
     * @param request :客户端请求
     * @param originalFileName :原始文件名
     * @return :
     */
    private static String getEncodedFilename(HttpServletRequest request, String originalFileName) {
        String encodedFilename = null;
        String agent = request.getHeader("User-Agent");
        if(agent.contains("MSIE")){
            //IE浏览器
            try {
                encodedFilename = URLEncoder.encode(originalFileName, "utf-8");
                encodedFilename = encodedFilename.replace("+", " ");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }else if(agent.contains("Firefox")){
            //火狐浏览器
            BASE64Encoder base64Encoder = new BASE64Encoder();
            encodedFilename = "=?utf-8?B?" + base64Encoder.encode(originalFileName.getBytes(StandardCharsets.UTF_8))+"?=";
        }else{
            //其他浏览器
            try {
                encodedFilename = URLEncoder.encode(originalFileName, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return encodedFilename;
    }

 

2.下载之后会出现乱码!!这个让我很头疼,一直在想着怎么转码,将文件处理为正确的编码格式

在查找资料的时候有人说用base64.encode(byte[]),这边我也尝试了一下,实际上转码之后获取的内容本身就是一串英文字母,下载之后可能还需要写前端代码对进行再次的转码,所以这个不可取

出错表现

另外给大家看下乱码之后的情况

流文件大小变成了2倍左右

Spring Boot下载踩坑实录,以及如何正确的下载服务器的资源到本地_第1张图片

 打开的时候提示这个

Spring Boot下载踩坑实录,以及如何正确的下载服务器的资源到本地_第2张图片

 打开内容进行比较的时候

Spring Boot下载踩坑实录,以及如何正确的下载服务器的资源到本地_第3张图片

 上图可见源文件所有中文在新文件里面都变成了乱码

抢救方法

  • 1.实际上出现问题的原因,在使用postmen,或者swagger访问下载接口的时候,获取的文件本身就不正确
  • 2.最后将请求方式从post改为了get请求,这样可以直接在浏览器上面进行下载了.
  • 3.如果使用post请求会相对来说麻烦一点,需要前端页面在获取请求结果时候处理一下

post请求下载文件

 

好了就这样了,这次踩坑实录就先这样了...继续加班改bug去了

你可能感兴趣的:(JavaWEB,BUG)