1.问题
需求是用户上传了多个文件,点击下载要下载包含这些文件的压缩包
我遇到的问题是,可以下载,但是压缩包是空的,无文件信息
接口返回了数据流
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.…