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

如何在Angular 2中判断服务端返回的Blob是PDF还是图片?

判断Blob内容是图片还是PDF的实用方案

我来给你几个实用的方案,帮你准确判断Blob里是图片还是PDF——毕竟直接硬设content-type确实容易踩坑,尤其是服务端没返回正确类型的时候:

方法一:通过文件头(Magic Number)判断(最准确)

每种文件格式都有独特的文件头标识(也就是常说的Magic Number),这个是最靠谱的判断依据,完全不受服务端返回的content-type影响。比如:

  • PDF的文件头是%PDF-(十六进制为25 50 44 46)
  • JPG的文件头是FF D8 FF
  • PNG的文件头是89 50 4E 47

你可以通过读取Blob的前几个字节来判断:

// 定义一个判断Blob类型的异步函数
function detectBlobType(blob: Blob): Promise<string> {
  return new Promise((resolve) => {
    const reader = new FileReader();
    
    reader.onload = function(e) {
      // 读取Blob的前4个字节(足够判断常见的图片和PDF类型)
      const arrayBuffer = e.target?.result as ArrayBuffer;
      const uint8Array = new Uint8Array(arrayBuffer.slice(0, 4));
      // 转成十六进制字符串,方便对比
      const headerHex = Array.from(uint8Array)
        .map(byte => byte.toString(16).padStart(2, '0'))
        .join('');

      // 根据文件头判断类型
      if (headerHex.startsWith('25504446')) {
        resolve('application/pdf');
      } else if (headerHex.startsWith('ffd8ff')) {
        resolve('image/jpeg');
      } else if (headerHex.startsWith('89504e47')) {
        resolve('image/png');
      } else if (headerHex.startsWith('47494638')) {
        resolve('image/gif');
      } else {
        // 未知类型的话,返回Blob原本的type或者标记为unknown
        resolve(blob.type || 'unknown');
      }
    };

    // 只读取前4个字节,节省资源
    reader.readAsArrayBuffer(blob.slice(0, 4));
  });
}

方法二:用Image对象尝试加载(简单直观)

如果你的场景里只有图片和PDF两种可能,可以尝试用浏览器的Image对象加载Blob:图片能正常加载,PDF则会触发错误。

function isImageBlob(blob: Blob): Promise<boolean> {
  return new Promise((resolve) => {
    const img = new Image();
    
    img.onload = () => {
      resolve(true);
      // 记得释放URL,避免内存泄漏
      URL.revokeObjectURL(img.src);
    };
    
    img.onerror = () => {
      resolve(false);
      URL.revokeObjectURL(img.src);
    };

    img.src = URL.createObjectURL(blob);
  });
}

这个方法的缺点是:如果Blob是损坏的图片,可能会误判成PDF,所以更适合作为辅助判断手段,或者和方法一结合使用。

结合到你的Angular代码里

你可以在downloadPDF方法中,用RxJS的switchMap把Blob流转换成带正确类型的Blob:

import { from } from 'rxjs';
import { switchMap, map } from 'rxjs/operators';

downloadPDF(fileId: string): Observable<Blob> {
  const header = new HttpHeaders().append('Accept', 'application/octet-stream');
  
  return this._http.get(this._api.powerLoadApi.getFileLink(this.WellId, fileId), {
    headers: header,
    responseType: 'blob',
  }).pipe(
    switchMap(res => {
      // 调用前面的detectBlobType函数,把Promise转成Observable
      return from(detectBlobType(res)).pipe(
        map(detectedType => {
          // 创建新的Blob,设置正确的content-type
          return new Blob([res], { type: detectedType });
        })
      );
    })
  );
}

额外提醒

如果服务端能在响应头里返回正确的Content-Type,那优先用这个值更省心:

// 在http.get的pipe里可以先读取响应头
.pipe(
  tap(res => {
    const contentType = res.headers.get('Content-Type');
    console.log('服务端返回的类型:', contentType);
  })
)

只有当服务端返回的是application/octet-stream或者类型不正确时,再用上面的判断方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:35:37