Java实现生成文件并将文件下载至浏览器默认路径的方法

一、生成文件

1.1 生成word文件

    /**
     * 生成 word 文件
     *
     * @param dataMap 待填充数据
     * @param templateName 模板文件名称
     * @param filePath 模板文件路径
     * @param fileName 生成的 word 文件名称
     */
    public static void createWord(Map dataMap, String templateName, String filePath, String fileName){
        // 创建配置实例
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
        // 设置编码
        configuration.setDefaultEncoding(StandardCharsets.UTF_8.name());
        // ftl模板文件
        configuration.setClassForTemplateLoading(ActionController.class, filePath);

        try {
            // 获取模板
            Template template = configuration.getTemplate(templateName);
//            response.setHeader("Content-disposition",
//                    "attachment;filename=" + URLEncoder.encode(fileName + ".doc", StandardCharsets.UTF_8.name()));
//             定义输出类型
//            response.setContentType("application/msword");
//            Writer out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream()));

            File outFile = new File(System.getProperties().getProperty("user.home") + File.separator + "filepath" + File.separator + fileName);
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));

            // 生成文件
            template.process(dataMap, out);

            out.flush();
            out.close();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

1.2 生成json文件

FileUtil是文件工具类,使用createNewFile方法可以生成json文件

package com.umetrip.qa.utils;

import com.alibaba.fastjson.JSONObject;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;

/**
 * @description:
 * @author: 孙东平
 * @time: 2020-10-28 11:42
 */
public class FileUtil {
    public static void createNewFile(String fileName, Object data) throws Exception{
        //1、创建文件对象
        File tempFile = new File(System.getProperties().getProperty("user.home") + File.separator + "filepath" + File.separator + fileName);
        File fileParent = tempFile.getParentFile();
        String fileParentPath = tempFile.getParent();
        System.out.println("fileParent:" + fileParent);
        System.out.println("fileParentPath:" + fileParentPath);

        //2、判断目录或文件是否存在
        if (!fileParent.exists()) {
            fileParent.mkdirs();// 能创建多级目录
        }
        if (!tempFile.exists())
            tempFile.createNewFile();//有路径才能创建文件
        System.out.println(tempFile);

        String path = tempFile.getPath();
        String absolutePath = tempFile.getAbsolutePath();//得到文件/文件夹的绝对路径
        String getFileName = tempFile.getName();//得到文件/文件夹的名字
        System.out.println("path:"+path);
        System.out.println("absolutePath:"+absolutePath);
        System.out.println("getFileName:"+getFileName);

        //3、写入数据
        FileOutputStream fos = new FileOutputStream(System.getProperties().getProperty("user.home") + File.separator + "filepath" + File.separator + fileName);
        String dataStr = JSONObject.toJSONString(data);
        byte[] bytes = dataStr.getBytes();
        fos.write(bytes);
        fos.close();
    }
//
//    public static void createNewFile(String fileName, Object data) throws Exception{
//        //1、创建文件对象
//        File tempFile = new File(System.getProperties().getProperty("user.home") + File.separator + "filepath" + File.separator + fileName);
//        File fileParent = tempFile.getParentFile();
//        String fileParentPath = tempFile.getParent();
//        System.out.println("fileParent:" + fileParent);
//        System.out.println("fileParentPath:" + fileParentPath);
//
//        //2、判断目录或文件是否存在
//        if (!fileParent.exists()) {
//            fileParent.mkdirs();// 能创建多级目录
//        }
//        if (!tempFile.exists())
//            tempFile.createNewFile();//有路径才能创建文件
//        System.out.println(tempFile);
//
//        String path = tempFile.getPath();
//        String absolutePath = tempFile.getAbsolutePath();//得到文件/文件夹的绝对路径
//        String getFileName = tempFile.getName();//得到文件/文件夹的名字
//        System.out.println("path:"+path);
//        System.out.println("absolutePath:"+absolutePath);
//        System.out.println("getFileName:"+getFileName);
//
//        //3、写入数据
//        FileOutputStream fos = new FileOutputStream(System.getProperties().getProperty("user.home") + File.separator + "filepath" + File.separator + fileName);
//        String dataStr = JSONObject.toJSONString(data);
//        byte[] bytes = dataStr.getBytes();
//        fos.write(bytes);
//        fos.close();
//    }

    /**
     * 文件下载
     * @param file
     * @throws IOException
     */
    public static ResponseEntity<InputStreamResource> downloadFile(File file) throws IOException {
        if (file.exists()) {
            FileSystemResource fileSource = new FileSystemResource(file);
            return downloadFile(fileSource.getInputStream(),fileSource.getFilename());
        }
        return null;
    }
    public static ResponseEntity<InputStreamResource> downloadFile(InputStream in, String fileName) {
        try {
            byte[] testBytes = new byte[in.available()];
            HttpHeaders headers = new HttpHeaders();
            headers.add("Access-Control-Expose-Headers", "Content-Disposition");
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", MarkUtil.convertFileName(fileName)));
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");
            return ResponseEntity
                    .ok()
                    .headers(headers)
                    .contentLength(testBytes.length)
                    .contentType(MediaType.parseMediaType("application/octet-stream"))
                    .body(new InputStreamResource(in));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

MarkUtil类

package com.umetrip.qa.utils;

import org.apache.commons.lang.StringUtils;

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

/**
 * @description:
 * @author: 孙东平
 * @time: 2021-07-05 16:06
 */
public class MarkUtil {
    /**
     * chinese code convert
     * @param fileName
     * @return
     */
    public static String convertFileName(String fileName) {
        System.out.println("fileName before: " + fileName);
        if(!StringUtils.isBlank(fileName)) {
            try {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        System.out.println("fileName after: " + fileName);
        return fileName;
    }
}

二、下载文件

2.1 方式一

使用 1.2 中 FileUtil的 downloadFile 方法

2.2 方式二

package com.taobao.rigel.rap.utils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @description:  将文件内容响应到浏览器
 * @author: 孙东平
 * @time: 2021-07-05 16:53
 */
public class DownloadUtil {
    // 字符编码格式
    private static String charsetCode = "utf-8";

    /**
     * 文件的内容类型
     */
    private static String getFileContentType(String name){
        String result = "";
        String fileType = name.toLowerCase();
        if (fileType.endsWith(".png")) {
            result = "image/png";
        } else if (fileType.endsWith(".gif")) {
            result = "image/gif";
        } else if (fileType.endsWith(".jpg") || fileType.endsWith(".jpeg")) {
            result = "image/jpeg";
        } else if(fileType.endsWith(".svg")){
            result = "image/svg+xml";
        }else if (fileType.endsWith(".doc")) {
            result = "application/msword";
        } else if (fileType.endsWith(".xls")) {
            result = "application/x-excel";
        } else if (fileType.endsWith(".zip")) {
            result = "application/zip";
        } else if (fileType.endsWith(".pdf")) {
            result = "application/pdf";
        } else {
            result = "application/octet-stream";
        }
        return result;
    }


    /**
     * 下载文件
     * @param path 文件的位置
     * @param fileName 自定义下载文件的名称
     * @param resp http响应
     * @param req http请求
     */
    public static void downloadFile(String path, String fileName, HttpServletResponse resp, HttpServletRequest req){

        try {
            File file = new File(path);
            /**
             * 中文乱码解决
             */
            String type = req.getHeader("User-Agent").toLowerCase();
            System.out.println("type:" + type);
            if(type.indexOf("firefox")>0 || type.indexOf("chrome")>0){
                /**
                 * 谷歌或火狐
                 */
//                fileName = new String(fileName.getBytes(charsetCode), "iso8859-1");
//                fileName = new String(fileName.getBytes(charsetCode), "utf-8");
                fileName = URLEncoder.encode(fileName, charsetCode);
            }else{
                /**
                 * IE
                 */
                fileName = URLEncoder.encode(fileName, charsetCode);
            }
            // 设置响应的头部信息
            resp.setHeader("content-disposition", "attachment;filename=" + fileName);
            // 设置响应内容的类型
            System.out.println("getFileContentType(fileName):" + getFileContentType(fileName));
            resp.setContentType(getFileContentType(fileName)+"; charset=" + charsetCode);
            // 设置响应内容的长度
            resp.setContentLength((int) file.length());
            // 输出
            outStream(new FileInputStream(file), resp.getOutputStream());
            System.out.println("resp: " + resp.toString());
        } catch (Exception e) {
            System.out.println("执行downloadFile发生了异常:" + e.getMessage());
        }
    }



    /**
     * 基础字节数组输出
     */
    private static void outStream(InputStream is, OutputStream os) {
        try {
            byte[] buffer = new byte[10240];
            int length = -1;
            while ((length = is.read(buffer)) != -1) {
                os.write(buffer, 0, length);
                os.flush();
            }
        } catch (Exception e) {
            System.out.println("执行 outStream 发生了异常:" + e.getMessage());
        } finally {
            try {
                os.close();
            } catch (IOException e) {
            }
            try {
                is.close();
            } catch (IOException e) {
            }
        }
    }
}

三、前端代码处理

当调好后端接口后,前端代码也需要进行相应的处理

export default {
  name: 'ApiPortType',
  data () {
    return {
      visible: false,
      radioType: 'doc',
      id: ''
    }
  },
  methods: {
    handleSubmit (e) {
      console.log(this.id)
      console.log(this.radioType)
      console.log('可以调接口了!!')
      console.log('工程名:' + this.$store.state.projectName)
      generateDocumentOfApi({projectName: this.$store.state.projectName, actionId: this.id, type: this.radioType}).then((res) => {
      // generateDocumentOfApi({id: '1535331', type: this.radioType}).then((res) => {
        let data = res.data
        let contentDisposition = res.headers['content-disposition']
        let fileName = contentDisposition.substring(contentDisposition.indexOf('"') + 1, contentDisposition.length - 1)
        console.log(fileName)
        console.log(decodeURIComponent(fileName))
        this.download(data, decodeURIComponent(fileName))
        console.log('调结束generateDocumentOfApi接口,去查看吧!!!!')
      })
    },
    // 下载文件
    download (data, fileName) {
      if (!data) {
        return
      }
      let type = fileName.split('.')[1]
      console.log('type:' + type)
      let url
      if (type === 'json') {
        // type: 'application/json'
        url = window.URL.createObjectURL(new Blob([JSON.stringify(data)]), {type: 'application/json'})

        // // encodeURIComponent解决中文乱码
        // let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(JSON.stringify(data))
        // // 通过创建a标签实现
        // let link = document.createElement('a')
        // link.href = uri
        // // 对下载的文件命名
        // link.download = '地区数据表.json'
        // document.body.appendChild(link)
        // link.click()
        // document.body.removeChild(link)
      } else if (type === 'doc') {
        url = window.URL.createObjectURL(new Blob([data]), {type: 'application/msword'})
      }
      console.log('url: ' + url)
      let link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.download = fileName
      // link.setAttribute('download', fileName)
      // document.body.appendChild(link)
      link.click()
      window.URL.revokeObjectURL(url)
    }
  }
}

效果:
在这里插入图片描述

四、解决url中文乱码问题

后端使用URLEncoder.encode(fileName, "UTF-8");编码
前端使用如下方式解码即可

// 解码用 
decodeURIComponent(str)
// 编码用 
encodeURIComponent(str)
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值