生成PDF并打包为Zip时报错0x800704CD,现有方案无效求代码排查
问题原因
你的代码存在多处严重的响应流操作冲突和逻辑错误,直接导致0x800704CD(远程主机强迫关闭连接)报错:
- 同一个
Document对象绑定了两个PdfWriter,同时往内存流和Response输出流写内容,导致输出内容混乱 - 你在
Download_PDF_Click一开始就已经将响应的ContentType设为application/zip,但在Create_PDF中又追加了PDF的Content-Disposition响应头,还往响应流写入PDF内容,浏览器收到不符合zip格式的内容后直接断开连接,触发报错 - 你提前设置了
Response.BufferOutput = false,内容会直接发送到客户端,还没生成完zip就写入了大量PDF内容,完全破坏了zip响应的格式 - 生成完zip后你只把文件存在了服务器磁盘,没有将zip内容写入响应发送给客户端,客户端等待超时后主动断开连接
PDF_list仅存储了PDF文件名,你没有将生成的PDF字节数组存为服务器文件,也没有直接将字节流加入压缩包,ZipFile.AddFiles无法找到对应文件- 资源释放顺序错误,应该先关闭
PdfWriter再关闭Document
修正方案
1. 核心调整思路
移除所有PDF生成过程中对Response的直接操作,所有PDF先在内存生成,全部完成后再统一生成压缩包,最后把压缩包写入响应,避免输出内容混杂。
2. 修正后的代码参考
// 声明存储PDF信息的结构,无需存本地磁盘,直接用内存字节流 public class PdfItem { public string FileName { get; set; } public byte[] Content { get; set; } } List<PdfItem> PDF_list = new List<PdfItem>(); protected void Download_PDF_Click(object sender, EventArgs e) { // 先清空响应,所有内容生成完成前不要修改响应配置 Response.Clear(); Response.BufferOutput = true; String archiveName = "Arhiva Inspectii.zip"; // 先生成所有选中的PDF,全程不操作Response foreach (String id_chbx in ID_Checkbox) { CheckBox chbx = tbl_inspectii.FindControl(id_chbx) as CheckBox; if(chbx != null && chbx.Checked) { String PDF_id = chbx.ID.Replace("ChBx", string.Empty); var pdf = Create_PDF(PDF_id); if(pdf != null) PDF_list.Add(pdf); } } // 生成压缩包,用内存流存储,无需写入服务器磁盘 using (MemoryStream zipMs = new MemoryStream()) { using (ZipFile zip = new ZipFile()) { // 把所有内存中的PDF直接加入压缩包 foreach(var pdf in PDF_list) { zip.AddEntry(pdf.FileName, pdf.Content); } zip.Save(zipMs); } // 所有内容生成完成后,再设置响应头、输出压缩包 Response.ContentType = "application/zip"; Response.AddHeader("content-disposition", "filename=\"" + archiveName + "\""); Response.BinaryWrite(zipMs.ToArray()); } Response.Flush(); Response.End(); } protected PdfItem Create_PDF(String id_insp_max) { using (MemoryStream ms = new MemoryStream()) { Document brosura = new Document(PageSize.A4); brosura.SetMargins(40, 40, 40, 40); // 仅绑定一个写内存流的PdfWriter,不要操作Response PdfWriter wri = PdfWriter.GetInstance(brosura, ms); brosura.Open(); // 此处保留你原有SQL查询、brosura.Add()的业务逻辑 // 注意确认titlu_pdf变量已正确赋值,作为PDF文件名 // 调整资源释放顺序 wri.Close(); brosura.Close(); return new PdfItem { FileName = titlu_pdf + ".pdf", Content = ms.ToArray() }; } }
额外注意点
- 如果SQL查询耗时较长,建议设置合理的请求超时时间,避免客户端等待超时断开
- 生成大量大体积PDF时建议先存临时服务器磁盘再加入压缩包,避免内存溢出
内容的提问来源于stack exchange,提问作者Beta_K
相关产品推荐
相关产品推荐

