正文
.net WebApi 批量文件进行压缩zip以二进制流传输至前端(Vue)下载
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
前言:最近接了个项目,需要进行将服务端生成的文件进行打包压缩供前端下载,百度查了下资料,决定采用SharpZipLib C#开园的压缩解压库进行服务器文件压缩,在实现过程,郁闷的是前端接收下载下来的压缩包,解压的时候一直报“文件损坏或文件格式不正确”,
在此记录下这过程,避免以后采坑。
接口端压缩方法(以二进制文件流传输至Http):
/// <summary>
/// 批量下载PDF word 文件压缩
/// </summary>
/// <param name="downloadZipReportModel"></param>
/// <returns></returns>
[HttpGet, HttpPost]
public void DownLoadZipByReporlFilename(DownloadZipReportModel downloadZipReportModel)
{
MemoryStream ms = new MemoryStream();//创建内存存储
byte[] buffer = null;
using (ZipFile file = ZipFile.Create(ms))
{
file.BeginUpdate();
file.NameTransform = new MyNameTransfom();
foreach (var r in downloadZipReportModel.ReportPdfAndWordModel)//downloadZipReportModel 是报告数据对象 里面保存着相关需要下载的文件路径
{
file.Add(HttpContext.Current.Server.MapPath($"~/" + r.WordUrl));
file.Add(HttpContext.Current.Server.MapPath($"~/" + r.PdfUrl)); }
file.CommitUpdate();
buffer = new byte[ms.Length];
ms.Position = ;
ms.Read(buffer, , buffer.Length);
ms.Flush();
ms.Close();
}
HttpContext.Current.Response.ContentType = "application/octet-stream;charset=GBK";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=download.zip");
HttpContext.Current.Response.BinaryWrite(buffer);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End(); }
public class MyNameTransfom : ICSharpCode.SharpZipLib.Core.INameTransform
{ #region INameTransform 成员 public string TransformDirectory(string name)
{
return null;
} public string TransformFile(string name)
{
return Path.GetFileName(name);
} #endregion
}
Vue 前端接收后端二进制文件流:
async downLoadZipByReportFilename(postData){//下载报告,postData 保存的是需要下载的文件路径对象 let that = this
var ajax = new XMLHttpRequest()
var strategyDownloadUrl=process.env.BASE_URL+"api/Report/DownLoadZipByReporlFilename";
ajax.responseType = 'blob'
ajax.open("post",strategyDownloadUrl,true)
ajax.setRequestHeader('Authorization','Bearer ' + this.$store.state.token)
ajax.setRequestHeader("Content-Type","application/json; charset=utf-8") ajax.onreadystatechange = function(){
if(this.readyState == ) {
if(this.status == ) {
//console.log(this.response) // should be a blob
if(this.response.type == "application/octet-stream"){
that.downloadHandler(this.response,'download.zip')
}else{
that.$message('您要下载的资源已被删除!','' , 'error')
}
} else if(this.responseText != "") {
}
} else if(this.readyState == ) {
if(this.status == ) {
this.responseType = "blob"
} else {
this.responseType = "text"
}
}
};
ajax.send(JSON.stringify(postData));
}, downloadHandler(content, filename) {//下载处理
var eleLink = document.createElement('a')
eleLink.download = filename
eleLink.style.display = 'none'
// 字符内容转变成blob地址
var blob = new Blob([content],{type: "application/octet-stream"})
eleLink.href = URL.createObjectURL(blob)
// 触发点击
document.body.appendChild(eleLink)
eleLink.click()
// 然后移除
document.body.removeChild(eleLink)
}
之前前端接收二进制文件流解压报错代码:
async downLoadZipByReporlFilename(postData){
var resp=await downLoadZipByReporlFilename(postData);//后端接口
if(resp){
console.log(resp);
let blob = new Blob([resp], {type: "application/octet-stream"});
let url = window.URL.createObjectURL(blob);
window.location.href = url;
}
}
解压报错原因:接口请求文件媒体格式没有声明成功