update at 2026-02-14 11:16:40
This commit is contained in:
@@ -270,6 +270,34 @@ function parseXlsxBuffer(buffer) {
|
||||
return toRawTable(rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断二进制是否为 Zip 容器(xlsx)魔数:50 4B。
|
||||
*/
|
||||
function isZipMagic(bufferLike) {
|
||||
if (!bufferLike || typeof bufferLike.byteLength !== 'number' || bufferLike.byteLength < 2) {
|
||||
return false;
|
||||
}
|
||||
const bytes = new Uint8Array(bufferLike, 0, 2);
|
||||
return bytes[0] === 0x50 && bytes[1] === 0x4b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断二进制是否为 OLE 容器(老 xls)魔数:D0 CF 11 E0 A1 B1 1A E1。
|
||||
*/
|
||||
function isOleMagic(bufferLike) {
|
||||
if (!bufferLike || typeof bufferLike.byteLength !== 'number' || bufferLike.byteLength < 8) {
|
||||
return false;
|
||||
}
|
||||
const bytes = new Uint8Array(bufferLike, 0, 8);
|
||||
const signature = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];
|
||||
for (let i = 0; i < signature.length; i += 1) {
|
||||
if (bytes[i] !== signature[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按文件名后缀自动分流解析器。
|
||||
*/
|
||||
@@ -281,6 +309,13 @@ function parseTableByFileName(fileName, payload) {
|
||||
if (lowerName.endsWith('.xlsx') || lowerName.endsWith('.xls')) {
|
||||
return parseXlsxBuffer(payload);
|
||||
}
|
||||
|
||||
// 兜底:后缀不可用时,通过文件魔数自动识别 Excel。
|
||||
if (payload && typeof payload === 'object' && typeof payload.byteLength === 'number') {
|
||||
if (isZipMagic(payload) || isOleMagic(payload)) {
|
||||
return parseXlsxBuffer(payload);
|
||||
}
|
||||
}
|
||||
throw new Error('仅支持 .csv / .xlsx / .xls 文件');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user