tools-min-ns 1.18.14 → 1.18.16

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.
package/README.md CHANGED
@@ -5,6 +5,10 @@ pnpm i tools-min-ns --save
5
5
  ```
6
6
 
7
7
  # updates
8
+ ## v1.18.16
9
+ fix: SystemUtil 流式下载
10
+ ## v1.18.15
11
+ fix: SystemUtil 优化下载功能
8
12
  ## v1.18.14
9
13
  fix: TransferUtil.getFileSizeByBytes
10
14
 
@@ -1,10 +1,15 @@
1
1
  declare namespace FileUtil {
2
2
  /**
3
- * 多个文件压缩成zip
4
- * @param fileList
5
- * @param onProgress
6
- * @returns
3
+ * 提取文件名的辅助函数
4
+ * @param url
5
+ * @param response
7
6
  */
8
- function getZipByFiles(fileList: File[], onProgress?: (file: string, percent: number) => void): Promise<File>;
7
+ function extractFilename(url: string, response: Response): string;
8
+ /**
9
+ * 简单提取文件扩展名的辅助函数
10
+ * @param url
11
+ */
12
+ function getExt(url: string): string;
13
+ const ellisipsFileName: (fileName: string | undefined, maxLength?: number) => string;
9
14
  }
10
15
  export default FileUtil;
@@ -1,182 +1,44 @@
1
- var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) {
3
- return value instanceof P ? value : new P(function (resolve) {
4
- resolve(value);
5
- });
6
- }
7
- return new (P || (P = Promise))(function (resolve, reject) {
8
- function fulfilled(value) {
9
- try {
10
- step(generator.next(value));
11
- } catch (e) {
12
- reject(e);
13
- }
14
- }
15
- function rejected(value) {
16
- try {
17
- step(generator["throw"](value));
18
- } catch (e) {
19
- reject(e);
20
- }
21
- }
22
- function step(result) {
23
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
24
- }
25
- step((generator = generator.apply(thisArg, _arguments || [])).next());
26
- });
27
- };
28
- var __generator = this && this.__generator || function (thisArg, body) {
29
- var _ = {
30
- label: 0,
31
- sent: function sent() {
32
- if (t[0] & 1) throw t[1];
33
- return t[1];
34
- },
35
- trys: [],
36
- ops: []
37
- },
38
- f,
39
- y,
40
- t,
41
- g;
42
- return g = {
43
- next: verb(0),
44
- "throw": verb(1),
45
- "return": verb(2)
46
- }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
47
- return this;
48
- }), g;
49
- function verb(n) {
50
- return function (v) {
51
- return step([n, v]);
52
- };
53
- }
54
- function step(op) {
55
- if (f) throw new TypeError("Generator is already executing.");
56
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
57
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
58
- if (y = 0, t) op = [op[0] & 2, t.value];
59
- switch (op[0]) {
60
- case 0:
61
- case 1:
62
- t = op;
63
- break;
64
- case 4:
65
- _.label++;
66
- return {
67
- value: op[1],
68
- done: false
69
- };
70
- case 5:
71
- _.label++;
72
- y = op[1];
73
- op = [0];
74
- continue;
75
- case 7:
76
- op = _.ops.pop();
77
- _.trys.pop();
78
- continue;
79
- default:
80
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
81
- _ = 0;
82
- continue;
83
- }
84
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
85
- _.label = op[1];
86
- break;
87
- }
88
- if (op[0] === 6 && _.label < t[1]) {
89
- _.label = t[1];
90
- t = op;
91
- break;
92
- }
93
- if (t && _.label < t[2]) {
94
- _.label = t[2];
95
- _.ops.push(op);
96
- break;
97
- }
98
- if (t[2]) _.ops.pop();
99
- _.trys.pop();
100
- continue;
1
+ var FileUtil;
2
+ (function (FileUtil) {
3
+ /**
4
+ * 提取文件名的辅助函数
5
+ * @param url
6
+ * @param response
7
+ */
8
+ function extractFilename(url, response) {
9
+ // 尝试从 Content-Disposition 头获取文件名
10
+ var contentDisposition = response.headers.get('content-disposition');
11
+ if (contentDisposition) {
12
+ var filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
13
+ if (filenameMatch && filenameMatch[1]) {
14
+ return filenameMatch[1].replace(/['"]/g, '');
101
15
  }
102
- op = body.call(thisArg, _);
103
- } catch (e) {
104
- op = [6, e];
105
- y = 0;
106
- } finally {
107
- f = t = 0;
108
16
  }
109
- if (op[0] & 5) throw op[1];
110
- return {
111
- value: op[0] ? op[1] : void 0,
112
- done: true
113
- };
17
+ // URL 提取文件名
18
+ var urlFilename = url.split('/').pop();
19
+ return urlFilename || 'download';
114
20
  }
115
- };
116
- var __values = this && this.__values || function (o) {
117
- var s = typeof Symbol === "function" && Symbol.iterator,
118
- m = s && o[s],
119
- i = 0;
120
- if (m) return m.call(o);
121
- if (o && typeof o.length === "number") return {
122
- next: function next() {
123
- if (o && i >= o.length) o = void 0;
124
- return {
125
- value: o && o[i++],
126
- done: !o
127
- };
128
- }
129
- };
130
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
131
- };
132
- import JSZip from 'jszip';
133
- var FileUtil;
134
- (function (FileUtil) {
21
+ FileUtil.extractFilename = extractFilename;
135
22
  /**
136
- * 多个文件压缩成zip
137
- * @param fileList
138
- * @param onProgress
139
- * @returns
23
+ * 简单提取文件扩展名的辅助函数
24
+ * @param url
140
25
  */
141
- function getZipByFiles(fileList, onProgress) {
142
- return __awaiter(this, void 0, void 0, function () {
143
- var zip, fileList_1, fileList_1_1, file_1, blob, file;
144
- var e_1, _a;
145
- return __generator(this, function (_b) {
146
- switch (_b.label) {
147
- case 0:
148
- zip = new JSZip();
149
- try {
150
- for (fileList_1 = __values(fileList), fileList_1_1 = fileList_1.next(); !fileList_1_1.done; fileList_1_1 = fileList_1.next()) {
151
- file_1 = fileList_1_1.value;
152
- zip.file(file_1.name, file_1);
153
- }
154
- } catch (e_1_1) {
155
- e_1 = {
156
- error: e_1_1
157
- };
158
- } finally {
159
- try {
160
- if (fileList_1_1 && !fileList_1_1.done && (_a = fileList_1.return)) _a.call(fileList_1);
161
- } finally {
162
- if (e_1) throw e_1.error;
163
- }
164
- }
165
- return [4 /*yield*/, zip.generateAsync({
166
- type: 'blob'
167
- }, function (item) {
168
- onProgress === null || onProgress === void 0 ? void 0 : onProgress(item.currentFile, item.percent);
169
- })];
170
- case 1:
171
- blob = _b.sent();
172
- file = new File([blob], "\u201C".concat(fileList[0].name, "\u201D\u7B49").concat(fileList.length, "\u4E2A\u6587\u4EF6.zip"), {
173
- type: blob.type
174
- });
175
- return [2 /*return*/, file];
176
- }
177
- });
178
- });
26
+ function getExt(url) {
27
+ var _a;
28
+ var ext = (_a = url.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase();
29
+ return ext || url;
179
30
  }
180
- FileUtil.getZipByFiles = getZipByFiles;
31
+ FileUtil.getExt = getExt;
32
+ FileUtil.ellisipsFileName = function (fileName, maxLength) {
33
+ if (maxLength === void 0) {
34
+ maxLength = 30;
35
+ }
36
+ if (!fileName) return '';
37
+ if (fileName.length > maxLength) {
38
+ var len = Math.floor((maxLength - 3) / 2);
39
+ return fileName.slice(0, len) + '...' + fileName.slice(-len);
40
+ }
41
+ return fileName;
42
+ };
181
43
  })(FileUtil || (FileUtil = {}));
182
44
  export default FileUtil;
@@ -20,7 +20,7 @@ declare namespace SystemUtil {
20
20
  * @example
21
21
  * downloadFile('http://XXX.txt','text.txt')
22
22
  */
23
- function downloadFile(url: string, name?: string): void;
23
+ function downloadFile(url: string, name?: string): Promise<void>;
24
24
  /**
25
25
  * 通过base64下载文件
26
26
  * @param base64 base64字符串
@@ -28,13 +28,13 @@ declare namespace SystemUtil {
28
28
  * @example
29
29
  * downloadFileByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==','text.txt')
30
30
  */
31
- function downloadFileByBase64(base64: string, name?: string): void;
31
+ function downloadFileByBase64(base64: string, name: string): void;
32
32
  /**
33
33
  * 通过Blob下载文件
34
- * @param response BlobPart
34
+ * @param response Blob
35
35
  * @param name 文件名
36
36
  */
37
- const downloadFileByBlob: (response: any, name: string) => void;
37
+ const downloadFileByBlob: (response: Blob, name: string) => void;
38
38
  /**
39
39
  * 拷贝文本至剪切板
40
40
  * @param text 文本
@@ -1,10 +1,129 @@
1
+ var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) {
3
+ return value instanceof P ? value : new P(function (resolve) {
4
+ resolve(value);
5
+ });
6
+ }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) {
9
+ try {
10
+ step(generator.next(value));
11
+ } catch (e) {
12
+ reject(e);
13
+ }
14
+ }
15
+ function rejected(value) {
16
+ try {
17
+ step(generator["throw"](value));
18
+ } catch (e) {
19
+ reject(e);
20
+ }
21
+ }
22
+ function step(result) {
23
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
24
+ }
25
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
26
+ });
27
+ };
28
+ var __generator = this && this.__generator || function (thisArg, body) {
29
+ var _ = {
30
+ label: 0,
31
+ sent: function sent() {
32
+ if (t[0] & 1) throw t[1];
33
+ return t[1];
34
+ },
35
+ trys: [],
36
+ ops: []
37
+ },
38
+ f,
39
+ y,
40
+ t,
41
+ g;
42
+ return g = {
43
+ next: verb(0),
44
+ "throw": verb(1),
45
+ "return": verb(2)
46
+ }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
47
+ return this;
48
+ }), g;
49
+ function verb(n) {
50
+ return function (v) {
51
+ return step([n, v]);
52
+ };
53
+ }
54
+ function step(op) {
55
+ if (f) throw new TypeError("Generator is already executing.");
56
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
57
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
58
+ if (y = 0, t) op = [op[0] & 2, t.value];
59
+ switch (op[0]) {
60
+ case 0:
61
+ case 1:
62
+ t = op;
63
+ break;
64
+ case 4:
65
+ _.label++;
66
+ return {
67
+ value: op[1],
68
+ done: false
69
+ };
70
+ case 5:
71
+ _.label++;
72
+ y = op[1];
73
+ op = [0];
74
+ continue;
75
+ case 7:
76
+ op = _.ops.pop();
77
+ _.trys.pop();
78
+ continue;
79
+ default:
80
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
81
+ _ = 0;
82
+ continue;
83
+ }
84
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
85
+ _.label = op[1];
86
+ break;
87
+ }
88
+ if (op[0] === 6 && _.label < t[1]) {
89
+ _.label = t[1];
90
+ t = op;
91
+ break;
92
+ }
93
+ if (t && _.label < t[2]) {
94
+ _.label = t[2];
95
+ _.ops.push(op);
96
+ break;
97
+ }
98
+ if (t[2]) _.ops.pop();
99
+ _.trys.pop();
100
+ continue;
101
+ }
102
+ op = body.call(thisArg, _);
103
+ } catch (e) {
104
+ op = [6, e];
105
+ y = 0;
106
+ } finally {
107
+ f = t = 0;
108
+ }
109
+ if (op[0] & 5) throw op[1];
110
+ return {
111
+ value: op[0] ? op[1] : void 0,
112
+ done: true
113
+ };
114
+ }
115
+ };
1
116
  /**
2
117
  * 系统工具
3
118
  * @description
4
119
  * @author nanshen
5
120
  * @creat 2021-09-15 14:24:57
6
121
  */
122
+ import FileUtil from '../file/FileUtil';
7
123
  import TransferUtil from '../transfer/TransferUtil';
124
+ import streamSaver from 'streamsaver';
125
+ var MITM = 'https://ns.nihaonanshen.com/assets/stream/mitm.html';
126
+ streamSaver.mitm = MITM;
8
127
  var SystemUtil;
9
128
  (function (SystemUtil) {
10
129
  /**
@@ -32,15 +151,104 @@ var SystemUtil;
32
151
  * downloadFile('http://XXX.txt','text.txt')
33
152
  */
34
153
  function downloadFile(url, name) {
35
- var a = document.createElement('a');
36
- a.setAttribute('href', url);
37
- if (name) a.setAttribute('download', name);
38
- a.setAttribute('target', '_blank');
39
- var clickEvent = document.createEvent('MouseEvents');
40
- clickEvent.initEvent('click', true, true);
41
- a.dispatchEvent(clickEvent);
154
+ var _a;
155
+ return __awaiter(this, void 0, void 0, function () {
156
+ var response, contentLength, total, finalFilename, fileStream, error_1;
157
+ return __generator(this, function (_b) {
158
+ switch (_b.label) {
159
+ case 0:
160
+ _b.trys.push([0, 2,, 3]);
161
+ return [4 /*yield*/, fetch(url, {
162
+ method: 'GET',
163
+ headers: {
164
+ 'Cache-Control': 'no-cache'
165
+ }
166
+ })];
167
+ case 1:
168
+ response = _b.sent();
169
+ if (!response.ok) throw new Error("HTTP error! status: ".concat(response.status));
170
+ contentLength = response.headers.get('content-length');
171
+ total = contentLength ? parseInt(contentLength, 10) : undefined;
172
+ finalFilename = name || FileUtil.extractFilename(url, response);
173
+ fileStream = streamSaver.createWriteStream(finalFilename, {
174
+ size: total
175
+ });
176
+ // 检查浏览器是否支持流式传输
177
+ if (window.WritableStream && ((_a = response.body) === null || _a === void 0 ? void 0 : _a.pipeTo)) {
178
+ // 直接管道传输(最高效)
179
+ return [2 /*return*/, response.body.pipeTo(fileStream).then(function () {
180
+ return console.log('下载完成');
181
+ }).catch(function (error) {
182
+ console.error('下载失败:', error);
183
+ throw error;
184
+ })];
185
+ } else {
186
+ // 降级方案:手动读取和写入
187
+ return [2 /*return*/, manualStreamDownload(response, fileStream)];
188
+ }
189
+ return [3 /*break*/, 3];
190
+ case 2:
191
+ error_1 = _b.sent();
192
+ console.error('下载失败:', error_1);
193
+ // 降级方案
194
+ fallbackDownload(url, name);
195
+ return [3 /*break*/, 3];
196
+ case 3:
197
+ return [2 /*return*/];
198
+ }
199
+ });
200
+ });
42
201
  }
43
202
  SystemUtil.downloadFile = downloadFile;
203
+ // 最终降级方案
204
+ function fallbackDownload(url, filename) {
205
+ var a = document.createElement('a');
206
+ a.href = url;
207
+ if (filename) a.download = filename;
208
+ a.target = '_blank';
209
+ a.style.display = 'none';
210
+ document.body.appendChild(a);
211
+ a.click();
212
+ document.body.removeChild(a);
213
+ }
214
+ // 手动流式下载(兼容性降级)
215
+ function manualStreamDownload(response, fileStream) {
216
+ var _a;
217
+ return __awaiter(this, void 0, void 0, function () {
218
+ var reader, writer, _b, done, value;
219
+ return __generator(this, function (_c) {
220
+ switch (_c.label) {
221
+ case 0:
222
+ reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();
223
+ writer = fileStream.getWriter();
224
+ if (!reader) throw new Error('无法获取响应流');
225
+ _c.label = 1;
226
+ case 1:
227
+ _c.trys.push([1,, 6, 8]);
228
+ _c.label = 2;
229
+ case 2:
230
+ if (!true) return [3 /*break*/, 5];
231
+ return [4 /*yield*/, reader.read()];
232
+ case 3:
233
+ _b = _c.sent(), done = _b.done, value = _b.value;
234
+ if (done) return [3 /*break*/, 5];
235
+ return [4 /*yield*/, writer.write(value)];
236
+ case 4:
237
+ _c.sent();
238
+ return [3 /*break*/, 2];
239
+ case 5:
240
+ return [3 /*break*/, 8];
241
+ case 6:
242
+ return [4 /*yield*/, writer.close()];
243
+ case 7:
244
+ _c.sent();
245
+ return [7 /*endfinally*/];
246
+ case 8:
247
+ return [2 /*return*/];
248
+ }
249
+ });
250
+ });
251
+ }
44
252
  /**
45
253
  * 通过base64下载文件
46
254
  * @param base64 base64字符串
@@ -49,24 +257,32 @@ var SystemUtil;
49
257
  * downloadFileByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==','text.txt')
50
258
  */
51
259
  function downloadFileByBase64(base64, name) {
52
- var myBlob = TransferUtil.getBlobByBase64(base64);
260
+ var myBlob = TransferUtil.getBlobByBase64(base64, 'application/octet-stream');
53
261
  if (!myBlob) return;
54
- var myUrl = URL.createObjectURL(myBlob);
55
- downloadFile(myUrl, name);
262
+ SystemUtil.downloadFileByBlob(myBlob, name);
56
263
  }
57
264
  SystemUtil.downloadFileByBase64 = downloadFileByBase64;
58
265
  /**
59
266
  * 通过Blob下载文件
60
- * @param response BlobPart
267
+ * @param response Blob
61
268
  * @param name 文件名
62
269
  */
63
270
  SystemUtil.downloadFileByBlob = function (response, name) {
64
- var myBlob = new Blob([response], {
65
- type: 'application/vnd.ms-excel,charset=utf-8'
271
+ var blob = new Blob([response], {
272
+ type: 'application/octet-stream'
66
273
  });
67
- if (!myBlob) return;
68
- var myUrl = URL.createObjectURL(myBlob);
69
- downloadFile(myUrl, name);
274
+ var objectUrl = window.URL.createObjectURL(blob);
275
+ var link = document.createElement('a');
276
+ link.style.display = 'none';
277
+ link.href = objectUrl;
278
+ link.download = name;
279
+ document.body.appendChild(link);
280
+ link.click();
281
+ document.body.removeChild(link);
282
+ // 延迟释放URL,确保下载完成
283
+ setTimeout(function () {
284
+ return window.URL.revokeObjectURL(objectUrl);
285
+ }, 100);
70
286
  };
71
287
  /**
72
288
  * 拷贝文本至剪切板
@@ -35,10 +35,11 @@ declare namespace TransferUtil {
35
35
  /**
36
36
  * base64转blob流
37
37
  * @param base64 base64字符串
38
+ * @param mimeString mime类型
38
39
  * @example
39
40
  * getBlobByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==') => new Blob(['text1', 'text2'], {type : 'text/plain'})
40
41
  */
41
- function getBlobByBase64(base64: string): Blob | undefined;
42
+ function getBlobByBase64(base64: string, mimeString?: string): Blob | undefined;
42
43
  /**
43
44
  * blob流转换为base64
44
45
  * @param blob blob流
@@ -82,19 +82,21 @@ var TransferUtil;
82
82
  /**
83
83
  * base64转blob流
84
84
  * @param base64 base64字符串
85
+ * @param mimeString mime类型
85
86
  * @example
86
87
  * getBlobByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==') => new Blob(['text1', 'text2'], {type : 'text/plain'})
87
88
  */
88
- function getBlobByBase64(base64) {
89
+ function getBlobByBase64(base64, mimeString) {
89
90
  var _a, _b, _c;
90
91
  if (BaseUtil.isEmpty(base64)) return undefined;
91
92
  var byteString;
92
- if (((_b = (_a = base64 === null || base64 === void 0 ? void 0 : base64.split(',')) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.indexOf('base64')) >= 0) byteString = atob(base64.split(',')[1]);
93
- //base64 解码
94
- else {
93
+ if (((_b = (_a = base64 === null || base64 === void 0 ? void 0 : base64.split(',')) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.indexOf('base64')) >= 0) {
94
+ byteString = atob(base64.split(',')[1]);
95
+ } else {
96
+ //base64 解码
95
97
  byteString = unescape((_c = base64.split(',')) === null || _c === void 0 ? void 0 : _c[1]);
96
98
  }
97
- var mimeString = base64.split(',')[0].split(':')[1].split(';')[0]; //mime类型 -- image/png
99
+ mimeString = mimeString || base64.split(',')[0].split(':')[1].split(';')[0]; //mime类型 -- image/png
98
100
  var ia = new Uint8Array(byteString.length); //创建视图
99
101
  for (var i = 0; i < byteString.length; i++) {
100
102
  ia[i] = byteString.charCodeAt(i);
@@ -1,10 +1,15 @@
1
1
  declare namespace FileUtil {
2
2
  /**
3
- * 多个文件压缩成zip
4
- * @param fileList
5
- * @param onProgress
6
- * @returns
3
+ * 提取文件名的辅助函数
4
+ * @param url
5
+ * @param response
7
6
  */
8
- function getZipByFiles(fileList: File[], onProgress?: (file: string, percent: number) => void): Promise<File>;
7
+ function extractFilename(url: string, response: Response): string;
8
+ /**
9
+ * 简单提取文件扩展名的辅助函数
10
+ * @param url
11
+ */
12
+ function getExt(url: string): string;
13
+ const ellisipsFileName: (fileName: string | undefined, maxLength?: number) => string;
9
14
  }
10
15
  export default FileUtil;
@@ -1,192 +1,49 @@
1
1
  "use strict";
2
2
 
3
- var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
4
- function adopt(value) {
5
- return value instanceof P ? value : new P(function (resolve) {
6
- resolve(value);
7
- });
8
- }
9
- return new (P || (P = Promise))(function (resolve, reject) {
10
- function fulfilled(value) {
11
- try {
12
- step(generator.next(value));
13
- } catch (e) {
14
- reject(e);
15
- }
16
- }
17
- function rejected(value) {
18
- try {
19
- step(generator["throw"](value));
20
- } catch (e) {
21
- reject(e);
22
- }
23
- }
24
- function step(result) {
25
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
26
- }
27
- step((generator = generator.apply(thisArg, _arguments || [])).next());
28
- });
29
- };
30
- var __generator = this && this.__generator || function (thisArg, body) {
31
- var _ = {
32
- label: 0,
33
- sent: function sent() {
34
- if (t[0] & 1) throw t[1];
35
- return t[1];
36
- },
37
- trys: [],
38
- ops: []
39
- },
40
- f,
41
- y,
42
- t,
43
- g;
44
- return g = {
45
- next: verb(0),
46
- "throw": verb(1),
47
- "return": verb(2)
48
- }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
49
- return this;
50
- }), g;
51
- function verb(n) {
52
- return function (v) {
53
- return step([n, v]);
54
- };
55
- }
56
- function step(op) {
57
- if (f) throw new TypeError("Generator is already executing.");
58
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
59
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
60
- if (y = 0, t) op = [op[0] & 2, t.value];
61
- switch (op[0]) {
62
- case 0:
63
- case 1:
64
- t = op;
65
- break;
66
- case 4:
67
- _.label++;
68
- return {
69
- value: op[1],
70
- done: false
71
- };
72
- case 5:
73
- _.label++;
74
- y = op[1];
75
- op = [0];
76
- continue;
77
- case 7:
78
- op = _.ops.pop();
79
- _.trys.pop();
80
- continue;
81
- default:
82
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
83
- _ = 0;
84
- continue;
85
- }
86
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
87
- _.label = op[1];
88
- break;
89
- }
90
- if (op[0] === 6 && _.label < t[1]) {
91
- _.label = t[1];
92
- t = op;
93
- break;
94
- }
95
- if (t && _.label < t[2]) {
96
- _.label = t[2];
97
- _.ops.push(op);
98
- break;
99
- }
100
- if (t[2]) _.ops.pop();
101
- _.trys.pop();
102
- continue;
103
- }
104
- op = body.call(thisArg, _);
105
- } catch (e) {
106
- op = [6, e];
107
- y = 0;
108
- } finally {
109
- f = t = 0;
110
- }
111
- if (op[0] & 5) throw op[1];
112
- return {
113
- value: op[0] ? op[1] : void 0,
114
- done: true
115
- };
116
- }
117
- };
118
- var __values = this && this.__values || function (o) {
119
- var s = typeof Symbol === "function" && Symbol.iterator,
120
- m = s && o[s],
121
- i = 0;
122
- if (m) return m.call(o);
123
- if (o && typeof o.length === "number") return {
124
- next: function next() {
125
- if (o && i >= o.length) o = void 0;
126
- return {
127
- value: o && o[i++],
128
- done: !o
129
- };
130
- }
131
- };
132
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
133
- };
134
- var __importDefault = this && this.__importDefault || function (mod) {
135
- return mod && mod.__esModule ? mod : {
136
- "default": mod
137
- };
138
- };
139
3
  Object.defineProperty(exports, "__esModule", {
140
4
  value: true
141
5
  });
142
- var jszip_1 = __importDefault(require("jszip"));
143
6
  var FileUtil;
144
7
  (function (FileUtil) {
145
8
  /**
146
- * 多个文件压缩成zip
147
- * @param fileList
148
- * @param onProgress
149
- * @returns
9
+ * 提取文件名的辅助函数
10
+ * @param url
11
+ * @param response
12
+ */
13
+ function extractFilename(url, response) {
14
+ // 尝试从 Content-Disposition 头获取文件名
15
+ var contentDisposition = response.headers.get('content-disposition');
16
+ if (contentDisposition) {
17
+ var filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
18
+ if (filenameMatch && filenameMatch[1]) {
19
+ return filenameMatch[1].replace(/['"]/g, '');
20
+ }
21
+ }
22
+ // 从 URL 提取文件名
23
+ var urlFilename = url.split('/').pop();
24
+ return urlFilename || 'download';
25
+ }
26
+ FileUtil.extractFilename = extractFilename;
27
+ /**
28
+ * 简单提取文件扩展名的辅助函数
29
+ * @param url
150
30
  */
151
- function getZipByFiles(fileList, onProgress) {
152
- return __awaiter(this, void 0, void 0, function () {
153
- var zip, fileList_1, fileList_1_1, file_1, blob, file;
154
- var e_1, _a;
155
- return __generator(this, function (_b) {
156
- switch (_b.label) {
157
- case 0:
158
- zip = new jszip_1.default();
159
- try {
160
- for (fileList_1 = __values(fileList), fileList_1_1 = fileList_1.next(); !fileList_1_1.done; fileList_1_1 = fileList_1.next()) {
161
- file_1 = fileList_1_1.value;
162
- zip.file(file_1.name, file_1);
163
- }
164
- } catch (e_1_1) {
165
- e_1 = {
166
- error: e_1_1
167
- };
168
- } finally {
169
- try {
170
- if (fileList_1_1 && !fileList_1_1.done && (_a = fileList_1.return)) _a.call(fileList_1);
171
- } finally {
172
- if (e_1) throw e_1.error;
173
- }
174
- }
175
- return [4 /*yield*/, zip.generateAsync({
176
- type: 'blob'
177
- }, function (item) {
178
- onProgress === null || onProgress === void 0 ? void 0 : onProgress(item.currentFile, item.percent);
179
- })];
180
- case 1:
181
- blob = _b.sent();
182
- file = new File([blob], "\u201C".concat(fileList[0].name, "\u201D\u7B49").concat(fileList.length, "\u4E2A\u6587\u4EF6.zip"), {
183
- type: blob.type
184
- });
185
- return [2 /*return*/, file];
186
- }
187
- });
188
- });
31
+ function getExt(url) {
32
+ var _a;
33
+ var ext = (_a = url.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase();
34
+ return ext || url;
189
35
  }
190
- FileUtil.getZipByFiles = getZipByFiles;
36
+ FileUtil.getExt = getExt;
37
+ FileUtil.ellisipsFileName = function (fileName, maxLength) {
38
+ if (maxLength === void 0) {
39
+ maxLength = 30;
40
+ }
41
+ if (!fileName) return '';
42
+ if (fileName.length > maxLength) {
43
+ var len = Math.floor((maxLength - 3) / 2);
44
+ return fileName.slice(0, len) + '...' + fileName.slice(-len);
45
+ }
46
+ return fileName;
47
+ };
191
48
  })(FileUtil || (FileUtil = {}));
192
49
  exports.default = FileUtil;
@@ -20,7 +20,7 @@ declare namespace SystemUtil {
20
20
  * @example
21
21
  * downloadFile('http://XXX.txt','text.txt')
22
22
  */
23
- function downloadFile(url: string, name?: string): void;
23
+ function downloadFile(url: string, name?: string): Promise<void>;
24
24
  /**
25
25
  * 通过base64下载文件
26
26
  * @param base64 base64字符串
@@ -28,13 +28,13 @@ declare namespace SystemUtil {
28
28
  * @example
29
29
  * downloadFileByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==','text.txt')
30
30
  */
31
- function downloadFileByBase64(base64: string, name?: string): void;
31
+ function downloadFileByBase64(base64: string, name: string): void;
32
32
  /**
33
33
  * 通过Blob下载文件
34
- * @param response BlobPart
34
+ * @param response Blob
35
35
  * @param name 文件名
36
36
  */
37
- const downloadFileByBlob: (response: any, name: string) => void;
37
+ const downloadFileByBlob: (response: Blob, name: string) => void;
38
38
  /**
39
39
  * 拷贝文本至剪切板
40
40
  * @param text 文本
@@ -1,5 +1,120 @@
1
1
  "use strict";
2
2
 
3
+ var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) {
5
+ return value instanceof P ? value : new P(function (resolve) {
6
+ resolve(value);
7
+ });
8
+ }
9
+ return new (P || (P = Promise))(function (resolve, reject) {
10
+ function fulfilled(value) {
11
+ try {
12
+ step(generator.next(value));
13
+ } catch (e) {
14
+ reject(e);
15
+ }
16
+ }
17
+ function rejected(value) {
18
+ try {
19
+ step(generator["throw"](value));
20
+ } catch (e) {
21
+ reject(e);
22
+ }
23
+ }
24
+ function step(result) {
25
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
26
+ }
27
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
28
+ });
29
+ };
30
+ var __generator = this && this.__generator || function (thisArg, body) {
31
+ var _ = {
32
+ label: 0,
33
+ sent: function sent() {
34
+ if (t[0] & 1) throw t[1];
35
+ return t[1];
36
+ },
37
+ trys: [],
38
+ ops: []
39
+ },
40
+ f,
41
+ y,
42
+ t,
43
+ g;
44
+ return g = {
45
+ next: verb(0),
46
+ "throw": verb(1),
47
+ "return": verb(2)
48
+ }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
49
+ return this;
50
+ }), g;
51
+ function verb(n) {
52
+ return function (v) {
53
+ return step([n, v]);
54
+ };
55
+ }
56
+ function step(op) {
57
+ if (f) throw new TypeError("Generator is already executing.");
58
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
59
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
60
+ if (y = 0, t) op = [op[0] & 2, t.value];
61
+ switch (op[0]) {
62
+ case 0:
63
+ case 1:
64
+ t = op;
65
+ break;
66
+ case 4:
67
+ _.label++;
68
+ return {
69
+ value: op[1],
70
+ done: false
71
+ };
72
+ case 5:
73
+ _.label++;
74
+ y = op[1];
75
+ op = [0];
76
+ continue;
77
+ case 7:
78
+ op = _.ops.pop();
79
+ _.trys.pop();
80
+ continue;
81
+ default:
82
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
83
+ _ = 0;
84
+ continue;
85
+ }
86
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
87
+ _.label = op[1];
88
+ break;
89
+ }
90
+ if (op[0] === 6 && _.label < t[1]) {
91
+ _.label = t[1];
92
+ t = op;
93
+ break;
94
+ }
95
+ if (t && _.label < t[2]) {
96
+ _.label = t[2];
97
+ _.ops.push(op);
98
+ break;
99
+ }
100
+ if (t[2]) _.ops.pop();
101
+ _.trys.pop();
102
+ continue;
103
+ }
104
+ op = body.call(thisArg, _);
105
+ } catch (e) {
106
+ op = [6, e];
107
+ y = 0;
108
+ } finally {
109
+ f = t = 0;
110
+ }
111
+ if (op[0] & 5) throw op[1];
112
+ return {
113
+ value: op[0] ? op[1] : void 0,
114
+ done: true
115
+ };
116
+ }
117
+ };
3
118
  var __importDefault = this && this.__importDefault || function (mod) {
4
119
  return mod && mod.__esModule ? mod : {
5
120
  "default": mod
@@ -14,7 +129,11 @@ Object.defineProperty(exports, "__esModule", {
14
129
  * @author nanshen
15
130
  * @creat 2021-09-15 14:24:57
16
131
  */
132
+ var FileUtil_1 = __importDefault(require("../file/FileUtil"));
17
133
  var TransferUtil_1 = __importDefault(require("../transfer/TransferUtil"));
134
+ var streamsaver_1 = __importDefault(require("streamsaver"));
135
+ var MITM = 'https://ns.nihaonanshen.com/assets/stream/mitm.html';
136
+ streamsaver_1.default.mitm = MITM;
18
137
  var SystemUtil;
19
138
  (function (SystemUtil) {
20
139
  /**
@@ -42,15 +161,104 @@ var SystemUtil;
42
161
  * downloadFile('http://XXX.txt','text.txt')
43
162
  */
44
163
  function downloadFile(url, name) {
45
- var a = document.createElement('a');
46
- a.setAttribute('href', url);
47
- if (name) a.setAttribute('download', name);
48
- a.setAttribute('target', '_blank');
49
- var clickEvent = document.createEvent('MouseEvents');
50
- clickEvent.initEvent('click', true, true);
51
- a.dispatchEvent(clickEvent);
164
+ var _a;
165
+ return __awaiter(this, void 0, void 0, function () {
166
+ var response, contentLength, total, finalFilename, fileStream, error_1;
167
+ return __generator(this, function (_b) {
168
+ switch (_b.label) {
169
+ case 0:
170
+ _b.trys.push([0, 2,, 3]);
171
+ return [4 /*yield*/, fetch(url, {
172
+ method: 'GET',
173
+ headers: {
174
+ 'Cache-Control': 'no-cache'
175
+ }
176
+ })];
177
+ case 1:
178
+ response = _b.sent();
179
+ if (!response.ok) throw new Error("HTTP error! status: ".concat(response.status));
180
+ contentLength = response.headers.get('content-length');
181
+ total = contentLength ? parseInt(contentLength, 10) : undefined;
182
+ finalFilename = name || FileUtil_1.default.extractFilename(url, response);
183
+ fileStream = streamsaver_1.default.createWriteStream(finalFilename, {
184
+ size: total
185
+ });
186
+ // 检查浏览器是否支持流式传输
187
+ if (window.WritableStream && ((_a = response.body) === null || _a === void 0 ? void 0 : _a.pipeTo)) {
188
+ // 直接管道传输(最高效)
189
+ return [2 /*return*/, response.body.pipeTo(fileStream).then(function () {
190
+ return console.log('下载完成');
191
+ }).catch(function (error) {
192
+ console.error('下载失败:', error);
193
+ throw error;
194
+ })];
195
+ } else {
196
+ // 降级方案:手动读取和写入
197
+ return [2 /*return*/, manualStreamDownload(response, fileStream)];
198
+ }
199
+ return [3 /*break*/, 3];
200
+ case 2:
201
+ error_1 = _b.sent();
202
+ console.error('下载失败:', error_1);
203
+ // 降级方案
204
+ fallbackDownload(url, name);
205
+ return [3 /*break*/, 3];
206
+ case 3:
207
+ return [2 /*return*/];
208
+ }
209
+ });
210
+ });
52
211
  }
53
212
  SystemUtil.downloadFile = downloadFile;
213
+ // 最终降级方案
214
+ function fallbackDownload(url, filename) {
215
+ var a = document.createElement('a');
216
+ a.href = url;
217
+ if (filename) a.download = filename;
218
+ a.target = '_blank';
219
+ a.style.display = 'none';
220
+ document.body.appendChild(a);
221
+ a.click();
222
+ document.body.removeChild(a);
223
+ }
224
+ // 手动流式下载(兼容性降级)
225
+ function manualStreamDownload(response, fileStream) {
226
+ var _a;
227
+ return __awaiter(this, void 0, void 0, function () {
228
+ var reader, writer, _b, done, value;
229
+ return __generator(this, function (_c) {
230
+ switch (_c.label) {
231
+ case 0:
232
+ reader = (_a = response.body) === null || _a === void 0 ? void 0 : _a.getReader();
233
+ writer = fileStream.getWriter();
234
+ if (!reader) throw new Error('无法获取响应流');
235
+ _c.label = 1;
236
+ case 1:
237
+ _c.trys.push([1,, 6, 8]);
238
+ _c.label = 2;
239
+ case 2:
240
+ if (!true) return [3 /*break*/, 5];
241
+ return [4 /*yield*/, reader.read()];
242
+ case 3:
243
+ _b = _c.sent(), done = _b.done, value = _b.value;
244
+ if (done) return [3 /*break*/, 5];
245
+ return [4 /*yield*/, writer.write(value)];
246
+ case 4:
247
+ _c.sent();
248
+ return [3 /*break*/, 2];
249
+ case 5:
250
+ return [3 /*break*/, 8];
251
+ case 6:
252
+ return [4 /*yield*/, writer.close()];
253
+ case 7:
254
+ _c.sent();
255
+ return [7 /*endfinally*/];
256
+ case 8:
257
+ return [2 /*return*/];
258
+ }
259
+ });
260
+ });
261
+ }
54
262
  /**
55
263
  * 通过base64下载文件
56
264
  * @param base64 base64字符串
@@ -59,24 +267,32 @@ var SystemUtil;
59
267
  * downloadFileByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==','text.txt')
60
268
  */
61
269
  function downloadFileByBase64(base64, name) {
62
- var myBlob = TransferUtil_1.default.getBlobByBase64(base64);
270
+ var myBlob = TransferUtil_1.default.getBlobByBase64(base64, 'application/octet-stream');
63
271
  if (!myBlob) return;
64
- var myUrl = URL.createObjectURL(myBlob);
65
- downloadFile(myUrl, name);
272
+ SystemUtil.downloadFileByBlob(myBlob, name);
66
273
  }
67
274
  SystemUtil.downloadFileByBase64 = downloadFileByBase64;
68
275
  /**
69
276
  * 通过Blob下载文件
70
- * @param response BlobPart
277
+ * @param response Blob
71
278
  * @param name 文件名
72
279
  */
73
280
  SystemUtil.downloadFileByBlob = function (response, name) {
74
- var myBlob = new Blob([response], {
75
- type: 'application/vnd.ms-excel,charset=utf-8'
281
+ var blob = new Blob([response], {
282
+ type: 'application/octet-stream'
76
283
  });
77
- if (!myBlob) return;
78
- var myUrl = URL.createObjectURL(myBlob);
79
- downloadFile(myUrl, name);
284
+ var objectUrl = window.URL.createObjectURL(blob);
285
+ var link = document.createElement('a');
286
+ link.style.display = 'none';
287
+ link.href = objectUrl;
288
+ link.download = name;
289
+ document.body.appendChild(link);
290
+ link.click();
291
+ document.body.removeChild(link);
292
+ // 延迟释放URL,确保下载完成
293
+ setTimeout(function () {
294
+ return window.URL.revokeObjectURL(objectUrl);
295
+ }, 100);
80
296
  };
81
297
  /**
82
298
  * 拷贝文本至剪切板
@@ -35,10 +35,11 @@ declare namespace TransferUtil {
35
35
  /**
36
36
  * base64转blob流
37
37
  * @param base64 base64字符串
38
+ * @param mimeString mime类型
38
39
  * @example
39
40
  * getBlobByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==') => new Blob(['text1', 'text2'], {type : 'text/plain'})
40
41
  */
41
- function getBlobByBase64(base64: string): Blob | undefined;
42
+ function getBlobByBase64(base64: string, mimeString?: string): Blob | undefined;
42
43
  /**
43
44
  * blob流转换为base64
44
45
  * @param blob blob流
@@ -92,19 +92,21 @@ var TransferUtil;
92
92
  /**
93
93
  * base64转blob流
94
94
  * @param base64 base64字符串
95
+ * @param mimeString mime类型
95
96
  * @example
96
97
  * getBlobByBase64('data:text/plain;base64,dGV4dDF0ZXh0Mg==') => new Blob(['text1', 'text2'], {type : 'text/plain'})
97
98
  */
98
- function getBlobByBase64(base64) {
99
+ function getBlobByBase64(base64, mimeString) {
99
100
  var _a, _b, _c;
100
101
  if (BaseUtil_1.default.isEmpty(base64)) return undefined;
101
102
  var byteString;
102
- if (((_b = (_a = base64 === null || base64 === void 0 ? void 0 : base64.split(',')) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.indexOf('base64')) >= 0) byteString = atob(base64.split(',')[1]);
103
- //base64 解码
104
- else {
103
+ if (((_b = (_a = base64 === null || base64 === void 0 ? void 0 : base64.split(',')) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.indexOf('base64')) >= 0) {
104
+ byteString = atob(base64.split(',')[1]);
105
+ } else {
106
+ //base64 解码
105
107
  byteString = unescape((_c = base64.split(',')) === null || _c === void 0 ? void 0 : _c[1]);
106
108
  }
107
- var mimeString = base64.split(',')[0].split(':')[1].split(';')[0]; //mime类型 -- image/png
109
+ mimeString = mimeString || base64.split(',')[0].split(':')[1].split(';')[0]; //mime类型 -- image/png
108
110
  var ia = new Uint8Array(byteString.length); //创建视图
109
111
  for (var i = 0; i < byteString.length; i++) {
110
112
  ia[i] = byteString.charCodeAt(i);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tools-min-ns",
3
3
  "description": "工具包适用于前端以及node",
4
- "version": "1.18.14",
4
+ "version": "1.18.16",
5
5
  "main": "lib/index.js",
6
6
  "license": "MIT",
7
7
  "author": "nanshen",
@@ -41,6 +41,7 @@
41
41
  "@babel/preset-typescript": "^7.10.4",
42
42
  "@types/node": "^20.5.0",
43
43
  "@types/react": "^17.0.21",
44
+ "@types/streamsaver": "^2.0.5",
44
45
  "core-js": "3",
45
46
  "del": "^5.1.0",
46
47
  "gulp": "^4.0.2",
@@ -52,6 +53,6 @@
52
53
  "typescript": "^4.9.5"
53
54
  },
54
55
  "dependencies": {
55
- "jszip": "^3.10.1"
56
+ "streamsaver": "^2.0.6"
56
57
  }
57
58
  }