ASP.NET MVC返回带PDF的JSON后文件损坏无法打开求助
解决ASP.NET MVC返回JSON包含PDF数据导致文件损坏的问题
问题根源
JSON协议本身不支持直接传输二进制数据,ASP.NET MVC默认会将byte[]类型序列化为Base64编码的字符串。但你的前端代码直接将这个Base64字符串当作原始二进制数据传入Blob,相当于把字符串的UTF-8编码字节写入了PDF文件,这就导致了PDF文件格式损坏无法正常打开。
修复方案
1. 服务端修改:将PDF字节数组转为Base64字符串
首先修改CombinedData类的PdfData字段类型为string,并在生成数据时将字节数组转换为Base64编码:
// 定义CombinedData类 public class CombinedData { public string Text { get; set; } public string PdfData { get; set; } // 改为string类型存储Base64编码 public string FileName { get; set; } } // 修改BuildPDF Action public ActionResult BuildPDF() { // <原有生成PDF的代码保持不变> PdfFileEditor oEditor = new PdfFileEditor(); oEditor.Concatenate(printdocs.ToArray(), printfinalStream); printfinalStream.Seek(0, SeekOrigin.Begin); var combinedData = new CombinedData { Text = msg, PdfData = Convert.ToBase64String(printfinalStream.ToArray()), // 转成Base64字符串 FileName = "Authorization_" + GetNewGuid() + ".pdf" }; return Json(combinedData, JsonRequestBehavior.AllowGet); }
2. 前端修改:将Base64字符串解码为二进制字节数组
在AJAX的success回调中,先把Base64字符串解码为原始的Uint8Array,再生成Blob进行下载:
$.ajax({ type: 'GET', url: '@Url.Action("PrintandEmailAuthorization", "Forms")', data: { // 原有参数保持不变 "LetterDated": obj.LetterDated, "AuthDated": obj.AuthDated, "ReturnBy": obj.ReturnBy, "ProtestMonth": obj.ProtestMonth, "TaxYear": obj.TaxYear, "FromFileNum": obj.FromFileNum, "ToFileNum": obj.ToFileNum, "Suffix": obj.Suffix, "PaperSource": obj.PaperSource, "LetterSignedBy": obj.LetterSignedBy, "Title": obj.Title, "ConsentAttorney": obj.ConsentAttorney, "includeexemption": obj.Includeexemption, "includethirdrequest": obj.Includethirdrequest, "includeconsent": obj.Includeconsent, "includeref": obj.Includeref, "AttorneyName": obj.AttorneyName, "AttorneyEmail": obj.AttorneyEmail, "TemplateName": obj.TemplateName, "TemplatePath": obj.TemplatePath, "Enclosures": obj.Enclosures, "OldContingencyFee": obj.OldContingencyFee, "NewContingencyFee": obj.NewContingencyFee, "ContactID": obj.ContactID, "OptionSelected": obj.OptionSelected, "IncludeMultLotsRe": obj.IncludeMultLotsRe, "VillTaxYear": obj.VillTaxYear, "isTest": false }, success: function (data) { alert(data.Text); // 将Base64字符串解码为二进制字节数组 const byteChars = atob(data.PdfData); const byteNums = new Array(byteChars.length); for (let i = 0; i < byteChars.length; i++) { byteNums[i] = byteChars.charCodeAt(i); } const byteArray = new Uint8Array(byteNums); // 创建Blob并触发下载 var blob = new Blob([byteArray], { type: 'application/pdf' }); var url = window.URL.createObjectURL(blob); var a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = data.FileName; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } });
额外说明
- Base64编码会让数据体积增加约33%,如果你的PDF文件很大,这种方案可能会影响传输效率。此时可以考虑拆分请求:先请求提示文本,再单独请求PDF文件(用原来的
File返回方式)。 - 确保服务端的
printfinalStream在转换为字节数组前已经重置了位置(Seek(0, SeekOrigin.Begin)),这一步你已经做了,没问题。
内容的提问来源于stack exchange,提问作者Jonathan Small
相关产品推荐
相关产品推荐

