Blazor WASM应用在新标签页打开PDF内存流遇异常求助
PDF在Edge浏览器打开/下载异常问题解决
问题描述
原本计划用Base64编码的PDF在浏览器新标签页打开,但在Windows环境的Edge浏览器测试时,新标签页显示空白,同时CPU占用急剧飙升,直至关闭浏览器才恢复,PDF完全无法显示。此外,原本可用的downloadFile脚本改用类似逻辑实现下载时,浏览器无下载提示,且同样出现CPU占用异常的情况,现需解决打开PDF的脚本问题。
相关代码
打开PDF的后端代码
using (var memoryStream = new MemoryStream()) { pdf.Save(memoryStream); string base64 = Convert.ToBase64String(memoryStream.ToArray()); string url = $"data:application/pdf;base64,{base64}"; JS.InvokeVoidAsync("open", url, "_blank"); }
尝试下载的后端代码
using (var memoryStream = new MemoryStream()) { pdf.Save(memoryStream); JS.InvokeAsync<object>( "downloadFile", uid + ".pdf", Convert.ToBase64String(memoryStream.ToArray()) ); };
前端使用的脚本
<script type="text/javascript"> function downloadFile(fileName, bytesBase64) { if (navigator.msSaveBlob) { var data = window.atob(bytesBase64); var bytes = new Uint8Array(data.length); for (var i = 0; i < data.length; i++) { bytes[i] = data.charCodeAt(i); } var blob = new Blob([bytes.buffer], { type: "application/octet-stream" }); navigator.msSaveBlob(blob, fileName); } else { var link = document.createElement('a'); link.download = fileName; link.href = "data:application/octet-stream;base64," + bytesBase64; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } </script> <script type="text/javascript"> function open(bytesBase64) { var blob = base64ToBlob(bytesBase64, "application/octet-stream"); var url = URL.createObjectURL(blob); window.open(url, "_blank"); } function base64ToBlob(base64, contentType) { var byteCharacters = atob(base64); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += 512) { var slice = byteCharacters.slice(offset, offset + 512); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, { type: contentType }); return blob; } </script>
问题原因与修复方案
核心问题分析
- MIME类型错误:打开PDF时使用
application/octet-stream通用二进制类型,Edge无法正确识别为PDF文件,导致渲染引擎异常、CPU占用飙升。 - Base64转Blob效率低下:原
base64ToBlob函数采用多层循环切片处理,大文件场景下会产生大量内存操作,引发性能问题;直接使用data URI加载大PDF也会给浏览器解析带来过高压力。 - data URI下载限制:Edge对大文件的
data URI下载支持有限,容易触发无响应或无下载提示的问题。
修复后的打开PDF逻辑
后端代码调整
无需生成data URI,直接传递Base64字符串给前端处理:
using (var memoryStream = new MemoryStream()) { pdf.Save(memoryStream); string base64 = Convert.ToBase64String(memoryStream.ToArray()); JS.InvokeVoidAsync("openPdf", base64); }
前端脚本修复
<script type="text/javascript"> function openPdf(bytesBase64) { // 正确指定PDF的MIME类型 const contentType = 'application/pdf'; // 简化Base64转Blob的逻辑,减少循环层级 const byteCharacters = atob(bytesBase64); const byteArray = new Uint8Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteArray[i] = byteCharacters.charCodeAt(i); } const blob = new Blob([byteArray], { type: contentType }); const url = URL.createObjectURL(blob); const newTab = window.open(url, "_blank"); // 新标签页加载完成后释放Blob URL,避免内存泄漏 newTab.addEventListener('load', () => { URL.revokeObjectURL(url); }); } </script>
下载逻辑同步修复
统一使用Blob URL替代data URI,解决下载无提示和CPU异常问题:
<script type="text/javascript"> function downloadFile(fileName, bytesBase64) { const contentType = 'application/pdf'; const byteCharacters = atob(bytesBase64); const byteArray = new Uint8Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteArray[i] = byteCharacters.charCodeAt(i); } const blob = new Blob([byteArray], { type: contentType }); if (navigator.msSaveBlob) { navigator.msSaveBlob(blob, fileName); } else { const link = document.createElement('a'); link.download = fileName; link.href = URL.createObjectURL(blob); link.style.display = 'none'; document.body.appendChild(link); link.click(); document.body.removeChild(link); // 立即释放Blob URL,减少内存占用 URL.revokeObjectURL(link.href); } } </script>
额外优化建议
- 避免传递大体积Base64:如果PDF文件超过10MB,建议后端直接返回文件流,前端通过
fetch接口获取后转换为Blob,降低Base64编码带来的性能开销和内存占用。 - 升级Edge浏览器:确保使用最新版本的Edge,旧版本对Blob和URL API的支持存在兼容性bug。
内容的提问来源于stack exchange,提问作者RannyMeier
相关产品推荐
相关产品推荐

