js将文件流转为文件

js将文件流转为文件

需求:

前端通过ajax请求后端,根据接收前端的参数生成相应的文件,并将文件返回到前端提供下载。

方案1:

通过ajax请求后端,将生成的文件直接通过response.write的方式直接将生成的文返回。
该方案失败,由于ajax请求返回的数据需要在回调函数中获取,返回的data没法直接转为文件下载。

方案2:

通过ajax请求后端,将生成的文件转为文件字符流返回到前端,前端使用Blob的方式将文件字符流数据写入文件,再下载。

具体实现代码如下

  • 后端代码
  1. 文件生成使用freemarker模版引擎
    /**
     * 
     * @param dataMap
     *            word中需要展示的动态数据
     * @param templateName
     *            word模板名称 eg:test.ftl
     * @param filePath
     *            文件生成的目标路径,eg:D:/wordFile/
     * @param fileName
     *            生成的文件名称,eg:test.doc
     */
    public File createWord(Map<String, Object> dataMap, String templateName, String filePath, String fileName) {
        // 输出文件
        File outFile = null;
        try {
            // 创建配置实例
            Configuration configuration = new Configuration();

            // 设置编码
            configuration.setDefaultEncoding(encode);

            // ftl模板文件统一放至 com.lun.template 包下面
            configuration.setClassForTemplateLoading(FreemarkService.class, templatePath);
            
            //设置错误显示方式
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            
            // 设置对象包装器
            configuration.setObjectWrapper(new DefaultObjectWrapper());
            
            //处理空值
            configuration.setClassicCompatible(true);
            
            // 获取模板
            Template template = configuration.getTemplate(templateName);

            // 输出文件
            outFile = new File(filePath + File.separator + fileName);

            // 如果输出目标文件夹不存在,则创建
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }

            // 将模板和数据模型合并生成文件
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), encode));

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

            // 关闭流
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return outFile;
    }
  1. 将生成的文件调用FileUtils工具类将文件转为字节流数据
        byte[] fileBuff = null;
        try {
            fileBuff = FileUtils.readFileToByteArray(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
  1. 将字节流数据转为字符流数据
    /**
     * 字节流转字符流
     * @param bytes
     * @return
     */
    private char[] getChars(byte[] bytes) {
        Charset cs = Charset.forName("UTF-8");
        ByteBuffer bb = ByteBuffer.allocate(bytes.length);
        bb.put(bytes).flip();
        CharBuffer cb = cs.decode(bb);
        return cb.array();
    }

以上完成将文件转为字符流后,可以直接返回到前端。

  • 前端代码

        // 下载文件方法 
        var downloadDoc = function(content, filename) { 
            var eleLink = document.createElement('a'); 
            eleLink.download = filename; 
            eleLink.style.display = 'none'; 
            // 字符内容转变成blob地址 
            var blob = new Blob([content]); 
            eleLink.href = URL.createObjectURL(blob); 
            // 自动触发点击 
            document.body.appendChild(eleLink); 
            eleLink.click(); 
            // 然后移除 
            document.body.removeChild(eleLink); 
        }; 

@content:后端返回的文件字符流数据
@filename:下载时显示的默认文件名
在ajax请求的回调函数中调用该方法即可触发文件下载的操作事件。

bolb介绍

 

二次优化(兼容IE11):

后端优化改进为返回base64字符串:

return Base64.encodeBase64String(fileBuff);

前端调整:

js中base64字符串转Uint8Array

// 下载文件方法 
var downloadDoc = function(fileData, filename) { 
    var content = base64ToUint8Array(fileData);
    var blob = new Blob([content]); 
    if (window.navigator.msSaveOrOpenBlob) {
        navigator.msSaveBlob(blob, filename);
    } else {
        var a = document.createElement('a');
        var url = window.URL.createObjectURL(blob);
        if (!url) {
            url = window.webkitURL.createObjectURL(blob);
        }
        a.href = url;
        a.download = filename;
        a.click();
        window.URL.revokeObjectURL(url);
    }
}; 
        
//base64字符串转array
var base64ToUint8Array = function(base64String) {
    var rawData = window.atob(base64String);
    var len = rawData.length;
    var buffer = new ArrayBuffer(len);
    var outputArray = new Uint8Array(buffer);
    while (--len) {
        outputArray[len] = rawData.charCodeAt(len);
    }
    return outputArray;
}

参考:兼容IE浏览器

  • 添加到短语集
     
    • history
    • 创建新的单词集...
  • 拷贝
初心回归,时光已逝!
原文地址:https://www.cnblogs.com/yin1361866686/p/11572920.html