nhanh-pure-function 1.3.20 → 1.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -226,28 +226,92 @@ export function _GetHrefName(href, defaultName = "file") {
226
226
  * @param {string} href - 文件路径
227
227
  * @param {string} [fileName] - 导出文件名
228
228
  */
229
- export async function _DownloadFile(href, fileName) {
230
- try {
231
- const response = await fetch(href); // 获取文件
232
- if (!response.ok) throw new Error("文件下载失败");
233
-
234
- const blob = await response.blob(); // 将响应转换为 Blob 对象
235
- const url = URL.createObjectURL(blob); // 创建文件 URL
236
-
237
- const a = document.createElement("a");
238
- a.href = url;
239
- a.download = fileName || _GetHrefName(href, "image");
240
-
241
- // 临时将 a 标签添加到 DOM,然后触发点击事件,最后移除
242
- document.body.appendChild(a);
243
- a.click();
244
- document.body.removeChild(a);
245
-
246
- // 释放 URL 对象
247
- URL.revokeObjectURL(url);
248
- } catch (error) {
249
- console.error("下载文件时发生错误:", error);
250
- }
229
+ export function _DownloadFile(href, fileName) {
230
+ return new Promise((resolve, reject) => {
231
+ _CheckConnectionWithXHR(href)
232
+ .then(() => {
233
+ try {
234
+ if (typeof fileName !== "string") {
235
+ fileName = _GetHrefName(href, "downloaded_file");
236
+ }
237
+
238
+ fetch(href)
239
+ .then((response) => {
240
+ if (!response.ok) {
241
+ throw new Error(`文件下载失败,状态码: ${response.status}`);
242
+ }
243
+ return response.blob();
244
+ })
245
+ .then((blob) => {
246
+ const url = URL.createObjectURL(blob); // 创建文件 URL
247
+
248
+ const a = document.createElement("a");
249
+ a.href = url;
250
+ a.download = decodeURIComponent(fileName);
251
+
252
+ // 临时将 a 标签添加到 DOM,然后触发点击事件,最后移除
253
+ document.body.appendChild(a);
254
+ a.click();
255
+ document.body.removeChild(a);
256
+
257
+ // 释放 URL 对象
258
+ URL.revokeObjectURL(url);
259
+
260
+ resolve();
261
+ })
262
+ .catch((error) => {
263
+ console.error("下载文件时发生错误:", error.message);
264
+ reject(error);
265
+ });
266
+ } catch (error) {
267
+ console.error("下载文件时发生错误:", error.message);
268
+ reject(error);
269
+ }
270
+ })
271
+ .catch(reject);
272
+
273
+ // try {
274
+ // // 验证 href 和 fileName 是否为合法字符串
275
+ // if (typeof href !== "string" || !href.trim()) {
276
+ // throw new Error("无效的 href 参数");
277
+ // }
278
+ // if (typeof fileName !== "string") {
279
+ // fileName = _GetHrefName(href, "downloaded_file");
280
+ // }
281
+
282
+ // fetch(href)
283
+ // .then((response) => {
284
+ // if (!response.ok) {
285
+ // throw new Error(`文件下载失败,状态码: ${response.status}`);
286
+ // }
287
+ // return response.blob();
288
+ // })
289
+ // .then((blob) => {
290
+ // const url = URL.createObjectURL(blob); // 创建文件 URL
291
+
292
+ // const a = document.createElement("a");
293
+ // a.href = url;
294
+ // a.download = decodeURIComponent(fileName);
295
+
296
+ // // 临时将 a 标签添加到 DOM,然后触发点击事件,最后移除
297
+ // document.body.appendChild(a);
298
+ // a.click();
299
+ // document.body.removeChild(a);
300
+
301
+ // // 释放 URL 对象
302
+ // URL.revokeObjectURL(url);
303
+
304
+ // resolve();
305
+ // })
306
+ // .catch((error) => {
307
+ // console.error("下载文件时发生错误:", error.message);
308
+ // reject(error);
309
+ // });
310
+ // } catch (error) {
311
+ // console.error("下载文件时发生错误:", error.message);
312
+ // reject(error);
313
+ // }
314
+ });
251
315
  }
252
316
 
253
317
  /**
@@ -556,16 +620,52 @@ export function _UpdateTargetByPath(model, path, value) {
556
620
  */
557
621
  export function _CheckConnectionWithXHR(url) {
558
622
  return new Promise((resolve, reject) => {
623
+ // 前置校验:确保 URL 合法
624
+ if (typeof url !== "string" || url.trim() === "" || !url.includes("://")) {
625
+ reject(new Error("Invalid URL: Must be a non-empty string"));
626
+ return;
627
+ }
628
+
629
+ // 显式处理浏览器兼容性错误(如无效协议或非法字符)
630
+ try {
631
+ const xhr = new XMLHttpRequest();
632
+ xhr.open("HEAD", url, true);
633
+ } catch (error) {
634
+ reject(new Error(`Invalid URL format: ${error.message}`));
635
+ return;
636
+ }
637
+
559
638
  const xhr = new XMLHttpRequest();
560
- xhr.open("HEAD", url, true); // 发送 HEAD 请求
639
+ xhr.open("HEAD", url, true);
640
+
641
+ // 统一错误处理逻辑
642
+ const handleError = (event) => {
643
+ reject(new Error(`Request failed: ${event.type}`));
644
+ };
645
+
561
646
  xhr.onreadystatechange = function () {
562
647
  if (xhr.readyState === XMLHttpRequest.DONE) {
563
- if (xhr.status >= 200 && xhr.status < 300) resolve();
564
- else reject(xhr);
648
+ // 兼容性处理:status=0 可能是跨域或网络错误
649
+ if (xhr.status === 0) {
650
+ reject(new Error("Network error or CORS blocked"));
651
+ } else if (xhr.status >= 200 && xhr.status < 300) {
652
+ resolve();
653
+ } else {
654
+ reject(new Error(`HTTP Error: ${xhr.status}`));
655
+ }
565
656
  }
566
657
  };
567
- xhr.onerror = reject;
568
- xhr.send();
658
+
659
+ // 绑定所有可能的错误事件
660
+ xhr.onerror = handleError; // 网络层错误(如 DNS 解析失败)
661
+ xhr.onabort = handleError; // 请求被中止
662
+ xhr.ontimeout = handleError; // 超时
663
+
664
+ try {
665
+ xhr.send();
666
+ } catch (error) {
667
+ reject(new Error(`Request send failed: ${error.message}`));
668
+ }
569
669
  });
570
670
  }
571
671
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nhanh-pure-function",
3
- "version": "1.3.20",
3
+ "version": "1.3.21",
4
4
  "description": "纯函数工具",
5
5
  "main": "lib/Index.js",
6
6
  "scripts": {