UNPKG

@glodon-aiot/react-components

Version:

aiot react components

154 lines (153 loc) 5.79 kB
var U = (c, Z, f) => new Promise((I, u) => { var P = (w) => { try { E(f.next(w)); } catch (t) { u(t); } }, p = (w) => { try { E(f.throw(w)); } catch (t) { u(t); } }, E = (w) => w.done ? I(w.value) : Promise.resolve(w.value).then(P, p); E((f = f.apply(c, Z)).next()); }); import { useState as h, useEffect as _, useCallback as M } from "react"; import { configure as A, BlobReader as L, ZipReader as R, HttpRangeReader as k, BlobWriter as H } from "@zip.js/zip.js"; import { ZIP_CHUNK_SIZE as O, MAX_FALLBACK_SIZE as y, MAX_ZIP_FILES as m, ZIP_ENTRIES_TIMEOUT as B, MAX_ZIP_FILE_SIZE as C, SAFE_FILE_TYPES as D } from "../constants.mjs"; import { checkRangeSupport as j, getFileSize as v } from "../utils.mjs"; import { getFileExtension as x, getFileType as W } from "../../../utils/file.mjs"; const S = { filenameEncoding: "utf-8" }, Q = (c) => { const [Z, f] = h([]), [I, u] = h(!0), [P, p] = h(null), [E, w] = h(null), [t, T] = h(null); _(() => { if (!c) { p("文件URL不能为空"), u(!1); return; } u(!0), p(null), f([]), w(null), t != null && t.blobUrl && (URL.revokeObjectURL(t.blobUrl), T(null)); let e = null; U(void 0, null, function* () { try { A({ chunkSize: O, useWebWorkers: !1 }); const { supportsRange: n, fileSize: r } = yield j(c); if (n) { const o = new k(c); e = new R(o, S); const b = (yield Promise.race([e.getEntries(), new Promise((i, a) => setTimeout(() => a(new Error("读取 ZIP 目录结构超时")), B))])).filter((i) => !i.directory).map((i) => ({ name: i.filename, size: i.uncompressedSize || 0, isDirectory: !1 })); b.sort((i, a) => i.name.localeCompare(a.name)), b.length > m ? (p(`ZIP 文件包含 ${b.length} 个文件,仅显示前 ${m} 个`), f(b.slice(0, m))) : f(b); } else { if (r > y) throw new Error(`服务器不支持 HTTP Range 请求,且文件过大(${Math.round(r / 1024 / 1024)}MB),无法预览。请下载后查看。`); const o = yield fetch(c); if (!o.ok) throw new Error(`HTTP error! status: ${o.status}`); const g = yield o.blob(), b = new L(g); e = new R(b, S); const a = (yield e.getEntries()).filter((s) => !s.directory).map((s) => ({ name: s.filename, size: s.uncompressedSize || 0, isDirectory: !1 })); a.sort((s, l) => s.name.localeCompare(l.name)), a.length > m ? (p(`ZIP 文件包含 ${a.length} 个文件,仅显示前 ${m} 个`), f(a.slice(0, m))) : f(a); } e && (yield e.close()), u(!1); } catch (n) { if (e) try { yield e.close(); } catch (o) { } const r = n.message || n.toString() || "加载 ZIP 文件失败"; if (r.includes("Range") || r.includes("range") || r.includes("HTTP Range not supported") || r.includes("超时")) try { const o = yield v(c); if (o > y) throw new Error(`文件过大(${Math.round(o / 1024 / 1024)}MB),无法通过 Range 请求加载,且文件过大无法下载整个文件预览。请下载后查看。`); const g = yield fetch(c); if (!g.ok) throw new Error(`HTTP error! status: ${g.status}`); const b = yield g.blob(), i = new L(b); e = new R(i, S); const s = (yield e.getEntries()).filter((l) => !l.directory).map((l) => ({ name: l.filename, size: l.uncompressedSize || 0, isDirectory: !1 })); s.sort((l, d) => l.name.localeCompare(d.name)), s.length > m ? (p(`ZIP 文件包含 ${s.length} 个文件,仅显示前 ${m} 个`), f(s.slice(0, m))) : f(s), e && (yield e.close()), u(!1); return; } catch (o) { const g = o.message || o.toString(); p(`ZIP 文件加载失败: ${r}。Fallback 方案也失败: ${g}`); } else p(r); u(!1); } }); }, [c]); const z = M((e) => U(void 0, null, function* () { if (E === e && t) { w(null), t.blobUrl && URL.revokeObjectURL(t.blobUrl), T(null); return; } w(e); try { let n = null, r; try { const s = new k(c); n = new R(s, S), r = (yield n.getEntries()).find((d) => d.filename === e); } catch (s) { const l = yield fetch(c); if (!l.ok) throw new Error(`HTTP error! status: ${l.status}`); const d = yield l.blob(), $ = new L(d); n = new R($, S), r = (yield n.getEntries()).find((F) => F.filename === e); } if (!r) throw new Error("文件不存在"); if (r.directory) throw new Error("无法预览目录"); if ((r.uncompressedSize || 0) > C) throw new Error("文件过大(超过 100MB),无法预览"); const g = yield r.getData(new H()), b = URL.createObjectURL(g), i = x(e), a = W(i); if (!D.includes(a)) throw new Error(`不支持预览 ${i || "未知"} 格式的文件`); T({ name: e, blobUrl: b, type: a }), n && (yield n.close()); } catch (n) { const r = n.message || n.toString() || "预览文件失败"; p(r); } }), [c, E, t]); return _(() => () => { t != null && t.blobUrl && URL.revokeObjectURL(t.blobUrl); }, [t]), { zipFiles: Z, zipLoading: I, zipError: P, selectedZipFile: E, zipFileContent: t, handleFileClick: z, setSelectedZipFile: w }; }; export { Q as useZipViewer };