刘光辉
4 小时以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { downloadByData } from '@jnpf/utils';
 
/** 从 Content-Disposition 解析文件名 */
export function fileNameFromDisposition(disposition?: string | null, fallback = 'export.xls') {
  if (!disposition) return fallback;
  const utf8 = /filename\*\s*=\s*UTF-8''([^;]+)/i.exec(disposition);
  if (utf8?.[1]) {
    try {
      return decodeURIComponent(utf8[1].trim().replace(/"/g, ''));
    } catch {
      return utf8[1].trim().replace(/"/g, '');
    }
  }
  const plain = /filename\s*=\s*("?)([^";]+)\1/i.exec(disposition);
  if (plain?.[2]) {
    try {
      return decodeURIComponent(plain[2].trim());
    } catch {
      return plain[2].trim();
    }
  }
  return fallback;
}
 
/** 保存后端导出的 Excel 流(axios 原生响应) */
export async function saveExportBlob(res: any, fallbackName: string) {
  const headers = res?.headers || {};
  const disposition = headers['content-disposition'] || headers['Content-Disposition'];
  const blob: Blob =
    res?.data instanceof Blob
      ? res.data
      : new Blob([res?.data], { type: 'application/vnd.ms-excel;charset=utf-8' });
 
  // 业务错误时常返回 JSON blob
  if (blob.type && blob.type.includes('application/json')) {
    const text = await blob.text();
    let msg = '导出失败';
    try {
      const json = JSON.parse(text);
      msg = json.msg || json.message || msg;
    } catch {
      // ignore
    }
    throw new Error(msg);
  }
 
  const fileName = fileNameFromDisposition(disposition, fallbackName);
  downloadByData(blob, fileName, 'application/vnd.ms-excel;charset=utf-8');
}