如何在C# MVC中用iframe展示2MB以上的PDF文件(含JS实现)
问题:网页展示5MB以内PDF的方案故障
此前用base64直接嵌入iframe可正常展示小于2MB的PDF,但尝试通过Blob+URL.createObjectURL方式适配更大文件时,无论文件大小均无法展示,还出现编码错误。
原可行代码
C# MVC控制器
// 原可行的控制器代码 var fData = Convert.ToBase64String(System.IO.File.ReadAllBytes(fname)); ViewData["base64String"] = fData;
前端.cshtml
<div> <iframe src="data:application/pdf;base64, @base64String" style="width:100%; height:500px" /> </div>
尝试失败的代码
C#控制器(冗余编码版本)
byte[] fileByte = System.IO.File.ReadAllBytes(filename); var temp = Convert.ToBase64String(fileByte); var res = Convert.ToBase64String(Encoding.UTF8.GetBytes(temp)); var pdf = string.Format("data:application/pdf;base64,{0}", fileContents[0]); ViewData["File"] = File(fileByte, "application/pdf"); ViewData["Byte"] = fileByte; ViewData["Encoded"] = res; ViewData["Content"] = fileContents; ViewData["pdf"] = pdf;
前端.cshtml(Blob方式)
@{ var base64String = ViewData["base64String"]; } <iframe id="viwer"> </iframe> <script> const blob = new Blob(['@base64String '], { type: 'application/pdf' }); var obj_url = URL.createObjectURL(blob) const iframe = document.getElementById("viwer"); iframe.setAttribute("src", obj_url); URL.revokeObjectURL(obj_url); </script>
尝试的编码转换代码(报错)
const byteCharacters = atob('@encStr'); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers);
解决方案
方案1:优化原base64方式(优先推荐)
现代浏览器对data URI的支持上限远高于5MB(Chrome/Firefox通常支持几十MB),原方案失效大概率是冗余编码或传递问题,调整后即可适配大文件:
控制器代码
public ActionResult ShowPdf() { string filename = "你的PDF文件路径"; byte[] fileBytes = System.IO.File.ReadAllBytes(filename); string base64Pdf = Convert.ToBase64String(fileBytes); ViewBag.Base64Pdf = base64Pdf; return View(); }
前端.cshtml代码
<iframe src="data:application/pdf;base64, @ViewBag.Base64Pdf" style="width: 100%; height: 800px; border: none;" ></iframe>
若仍有问题,检查服务器配置:在
web.config中调整maxRequestLength或maxAllowedContentLength,放开响应大小限制。
方案2:正确的Blob+URL.createObjectURL方式
之前的Blob方案错误在于直接将base64字符串当作二进制数据传入,需先解码为Uint8Array再创建Blob:
控制器代码(仅传递原始base64,无需二次编码)
public ActionResult ShowPdfWithBlob() { string filename = "你的PDF文件路径"; byte[] fileBytes = System.IO.File.ReadAllBytes(filename); string base64Pdf = Convert.ToBase64String(fileBytes); ViewBag.Base64Pdf = base64Pdf; return View(); }
前端.cshtml代码
<iframe id="pdfViewer" style="width:100%; height:800px; border:none;"></iframe> <script> const base64Str = '@ViewBag.Base64Pdf'; // 解码base64为二进制数组 const byteCharacters = atob(base64Str); const byteArray = new Uint8Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteArray[i] = byteCharacters.charCodeAt(i); } // 创建Blob并生成URL const blob = new Blob([byteArray], { type: 'application/pdf' }); const blobUrl = URL.createObjectURL(blob); // 赋值给iframe const viewer = document.getElementById('pdfViewer'); viewer.src = blobUrl; // 页面卸载时释放URL(可选,浏览器会自动回收,手动释放更严谨) window.addEventListener('unload', () => { URL.revokeObjectURL(blobUrl); }); </script>
注:之前的编码错误是因为控制器对base64做了二次编码(
Convert.ToBase64String(Encoding.UTF8.GetBytes(temp))),导致前端解码得到错误字符串。
方案3:直接返回文件流(最稳定的大文件方案)
若上述方案仍有问题,可让控制器直接返回PDF文件流,前端iframe直接指向该Action:
控制器代码
public FileResult GetPdf() { string filename = "你的PDF文件路径"; byte[] fileBytes = System.IO.File.ReadAllBytes(filename); return File(fileBytes, "application/pdf", Path.GetFileName(filename)); }
前端.cshtml代码
<iframe src="@Url.Action("GetPdf", "你的控制器名")" style="width:100%; height:800px; border:none;" ></iframe>
该方式无需处理编码,由浏览器直接处理文件流,适配所有大小的PDF(只要服务器配置允许)。
内容的提问来源于stack exchange,提问作者LittleTiredMan
相关产品推荐
相关产品推荐

