You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

问题原因与修复方案

核心问题分析

  1. MIME类型错误:打开PDF时使用application/octet-stream通用二进制类型,Edge无法正确识别为PDF文件,导致渲染引擎异常、CPU占用飙升。
  2. Base64转Blob效率低下:原base64ToBlob函数采用多层循环切片处理,大文件场景下会产生大量内存操作,引发性能问题;直接使用data URI加载大PDF也会给浏览器解析带来过高压力。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 09:39:52