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

如何创建包含ANSI(windows-1252)数据而非UTF-8的Blob对象

解决Angular中PDF下载时二进制数据被UTF-8编码破坏的问题

问题根源

你遇到的核心问题是把二进制PDF数据当成字符串处理了。当你将字符串类型的buffer传入Blob构造函数时,浏览器会自动用UTF-8编码重新解析这个字符串,导致原始二进制数据被篡改,文件大小翻倍且无法正常打开。PDF是二进制文件,根本不存在"ANSI/UTF-8编码"的说法——你需要的是原封不动保存原始二进制字节,而非处理文本编码。

解决方案步骤

  1. 修正API请求的响应类型
    在Angular的HttpClient请求中,必须指定responseType: 'arraybuffer',确保拿到的是原始二进制数据,而非自动转换后的字符串:

    // 示例:获取PDF数据的API请求
    this.http.get('/api/pdf/download', { responseType: 'arraybuffer' })
      .subscribe((buffer: ArrayBuffer) => {
        this.saveAsPdfFile(buffer, 'example.pdf', 'application/pdf');
      });
    
  2. 修改保存方法的参数与实现
    将buffer的类型从string改为ArrayBuffer或Uint8Array,直接用二进制数据创建Blob,不需要指定charset(对二进制文件无效):

    /**
     * 保存PDF文件到本地
     * @param buffer 原始二进制PDF数据(ArrayBuffer类型)
     * @param fileName 保存的文件名
     * @param fileType 文件类型
     */
    private saveAsPdfFile(buffer: ArrayBuffer, fileName: string, fileType: string): void {
      // 直接用ArrayBuffer创建Blob,无需指定charset
      const data: Blob = new Blob([buffer], { type: fileType });
    
      // 使用a标签下载的方式
      const downloadLink = document.createElement('a');
      downloadLink.href = URL.createObjectURL(data);
      downloadLink.setAttribute('download', fileName);
      document.body.appendChild(downloadLink);
      downloadLink.click();
      document.body.removeChild(downloadLink);
      URL.revokeObjectURL(downloadLink.href); // 释放URL对象,避免内存泄漏
    }
    

为什么之前的尝试无效?

  • 给Blob指定charset=windows-1252是无效的,因为Blob的charset参数仅对文本类型有效,二进制文件不需要编码声明。
  • 将二进制数据以字符串形式传递时,浏览器会把每个字节当成UTF-8字符处理,部分字节会被转义或扩展,导致原始数据完全损坏。

额外注意事项

  • 如果使用FileSaver库,直接传入Blob对象而非URL,效果一致:
    // 使用FileSaver的写法
    FileSaver.saveAs(data, fileName);
    
  • 确保API接口返回的响应头Content-Type是application/pdf,避免浏览器对响应做额外解析。

内容的提问来源于stack exchange,提问作者E Lewis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:33:37