前端下载压缩包,解压文件为空

1,822 阅读2分钟

1.问题

需求是用户上传了多个文件,点击下载要下载包含这些文件的压缩包

242be9e3deff6f6112ced1cfe4c2ac3.png 我遇到的问题是,可以下载,但是压缩包是空的,无文件信息

a9c8275b748d3ad39a55e4b94c5f3bf.png

接口返回了数据流

07002a2663835d2ce245877b5be3da6.png

2.解决后前端代码

下载和数据处理代码如下:

封装好的下载方法

//打包下载
export function reportZipDownload(data) {
  return request({
    responseType: 'blob',
    url: '/api/reportZipDownload?url='+data,
    method: 'post',
  })
}

可以使用常规的、自己的写法发起请求,以上代码段最重要的是

responseType: 'blob'

处理数据如下

fileLoad(row){
        let urlList = []
        if(row.abilityUrl){
          urlList.push(row.abilityUrl)
        }
        if(row.emergencyUrl){
          urlList.push(row.emergencyUrl)
        }
        if(row.riskUrl){
          urlList.push(row.riskUrl)
        }
        let zipName = row.officeName+'-'+row.countyName+row.streetName + '评估报告'
        // console.log(urlList.toString())
        reportZipDownload(urlList).then(res=>{
          this.exportExcel(res,zipName)
        })
        // utils.downloadFile(row.abilityUrl)
      },
     //导出处理
      exportExcel(response,title){
        let blob = new Blob([response], {type: 'application/zip'});
        let downloadElement = document.createElement('a');
        let href = window.URL.createObjectURL(blob); // 创建下载的链接
        downloadElement.href = href;
        downloadElement.download = title+'.zip'; // 下载后文件名
        document.body.appendChild(downloadElement);
        downloadElement.click(); // 点击下载
        document.body.removeChild(downloadElement); // 下载完成移除元素
        window.URL.revokeObjectURL(href); // 释放掉blob对象
      },
    }

3.后端代码(我不太懂,但是粘来做个记录)

/**\
     * 报告下载(压缩包)\
     * zxb\
     */\
    @ResponseBody\
    @RequestMapping("/reportZipDownload")\
    public void reportZipDownload(HttpServletRequest request, HttpServletResponse response, String url,String reportName) throws IOException {\
        List<String> urlList = SubjectUtils.getDateByComma(url);\
        List<String> urlPath = new ArrayList<>();\
        for(String str : urlList){\
            urlPath.add(Global.getFileServer()+"/"+str);\
        }\
        downloadAllFile(request,response,urlPath,"test");\
    }\
    /**\
     * 将多个文件进行压缩打包,解决文件名下载后的乱码问题\
     *\
     */\
    public void downloadAllFile(HttpServletRequest request, HttpServletResponse response, List<String> urlList,String name) throws UnsupportedEncodingException {\
        String downloadName = name+".zip";\
        String userAgent = request.getHeader("User-Agent");\
        // 针对IE或者以IE为内核的浏览器:\
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {\
            downloadName = ![]()java.net.URLEncoder.encode(downloadName, "UTF-8");\
        } else {\
            // 非IE浏览器的处理:\
            downloadName = new String(downloadName.getBytes("UTF-8"), "ISO-8859-1");\
        }\
        //经过上面的名称处理即可解决文件名下载后乱码的问题\
        response.setContentType("application/octet-stream; charset=utf-8");\
        response.setHeader("Content-Disposition""attachment; filename=" + downloadName);\
        OutputStream outputStream = null;\
        ZipOutputStream zos = null;\
        try {\
//            String baseDir = Constants.ExcelModelPath;\
//            outputStream = new FileOutputStream(baseDir+downloadName);\
\
            outputStream = response.getOutputStream();\
            zos = new ZipOutputStream(outputStream);\
            // 将文件流写入zip中,此方法在下面贴出\
            FileUtils.fileServerZipDownload(zos,urlList);\
        } catch (IOException e) {\
            logger.error("downloadAllFile-下载全部附件失败",e);\
        }finally {\
            if(zos != null) {\
                try {\
                    zos.close();\
                } catch (Exception e2) {\
                    ![]()logger.info("关闭输入流时出现错误",e2);\
                }\
            }\
            if(outputStream != null) {\
                try {\
                    outputStream.close();\
                } catch (Exception e2) {\
                    ![]()logger.info("关闭输入流时出现错误",e2);\
                }\
            }\
\
        }\
\
    }

4.总结

vue中导出下载最关键的就是处理数据流,关于js的几个二进制类Blob、ArrayBuffer和Buffer

(1).其中Blob是js对大数据块,整个文件的操作,File继承于Blob,Blob可以生成Blob URL,进而进行图片下载(生成a标签)、图片展示(放到img的src中)使用FileReaderAPI将Blob转回为ArrayBuffer Data URL(base64)等类型,blob对象无法对二进制细节的控制,但是有slice方法可以将数据分段。

 

(2).ArrayBuffer可以由fileReader的readAsArrayBuffer将Blob转化而成,之后可以使用DataView转换成TypedArray,然后进行二进制数据的操纵。

 

(3).Buffer是Nodejs中的概念,一般用法接收数据,拼接数据,最后toString转编码。nodejs.cn/api/buffer.…

Blob、ArrayBuffer和Buffer详细介绍