Skip to content

Commit af38df3

Browse files
committed
feat: ✨ 支持直接返回压缩包 Blob 对象
1 parent b262e86 commit af38df3

5 files changed

Lines changed: 131 additions & 28 deletions

File tree

apps/libs/downloader/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# downloader
22

3+
## 1.2.0
4+
5+
### Minor Changes
6+
7+
- 支持直接返回压缩包 Blob 对象
8+
39
## 1.1.0
410

511
### Minor Changes

apps/libs/downloader/README.md

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,73 @@
1717

1818
## 📖 使用方式
1919

20-
1. 添加 `// @require https://**/downloader.js?sha384-*` 库引用
21-
2. 添加 `// @grant GM_download` 下载权限
22-
3. 使用 `downloader` 方法下载资源
20+
### ✍ 添加元数据
2321

2422
```typescript
2523
// ==UserScript==
2624
// @require https://**/downloader.js?sha384-*
2725
// @grant GM_download
2826
// ==/UserScript==
27+
```
28+
29+
### 📥 参数说明
30+
31+
**Options 参数说明:**
32+
33+
| 参数名 | 类型 | 是否必填 | 默认值 | 说明 |
34+
| ------------- | -------------------------------- | -------- | ------ | -------------------------------------------------------------------------------- |
35+
| `filename` | string || | 保存的文件名,**添加此参数时会将压缩包保存到本地,未配置返回压缩包的 Blob 对象** |
36+
| `resources` | Resource[] || | 资源列表,数组,每个元素为对象,包含 `name``url` 或者 `blob` 字段 |
37+
| `concurrency` | number || `10` | 并发数,默认 `10` |
38+
| `onProgress` | (index: number) => Promise<void> || | 下载进度回调函数,参数为当前正在下载的资源索引 |
39+
40+
**Resource 参数说明:**
41+
42+
| 参数名 | 类型 | 是否必填 | 默认值 | 说明 |
43+
| ------ | ------ | -------- | ------ | ------------- |
44+
| `name` | string || | 资源名称 |
45+
| `url` | string || | URL 类型资源 |
46+
| `blob` | Blob || | Blob 类型资源 |
47+
48+
### 📦 使用示例
2949

30-
(async () => {
31-
'use strict'
32-
await downloader({
33-
filename: 'index.zip', // 文件名
34-
resources: [ // 资源列表
35-
{ name: 'index.html', url: location.href },
36-
],
37-
concurrency: 10, // 并发数
38-
onProgress(index) { // 下载进度回调
39-
console.log(`正在下载第 ${index + 1} 个资源`)
50+
**下载,压缩,并保存到本地**
51+
52+
```typescript
53+
await downloader({
54+
filename: 'index.zip',
55+
resources: [
56+
{ name: 'index.html', url: location.href },
57+
{
58+
name: 'hello.txt',
59+
blob: new Blob(['hello world'], { type: 'text/plain' }),
60+
},
61+
],
62+
concurrency: 10,
63+
async onProgress(index) {
64+
console.log(`正在下载第 ${index + 1} 个资源`)
65+
},
66+
})
67+
```
68+
69+
**仅下载和压缩**
70+
71+
```typescript
72+
const blob = await downloader({
73+
resources: [
74+
{ name: 'index.html', url: location.href },
75+
{
76+
name: 'hello.txt',
77+
blob: new Blob(['hello world'], { type: 'text/plain' }),
4078
},
41-
})
42-
})()
79+
],
80+
concurrency: 10,
81+
async onProgress(index) {
82+
console.log(`正在下载第 ${index + 1} 个资源`)
83+
},
84+
})
85+
// 自行处理
86+
// GM_download(URL.createObjectURL(blob), 'index.zip')
4387
```
4488

4589
## 🚨 免责声明

apps/libs/downloader/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "downloader",
33
"type": "module",
4-
"version": "1.1.0",
4+
"version": "1.2.0",
55
"private": true,
66
"description": "Downloader -- 资源下载器(下载资源、Zip 压缩、下载到本地)",
77
"author": {

apps/libs/downloader/src/index.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,55 @@
1-
import { BlobWriter, HttpReader, ZipWriter } from '@zip.js/zip.js'
1+
import { BlobReader, BlobWriter, HttpReader, ZipWriter } from '@zip.js/zip.js'
22
import pLimit from 'p-limit'
33

4-
export interface Resource {
4+
export interface UrlResource {
55
name: string
66
url: string | URL
77
}
88

9-
export interface Options {
10-
filename: string
9+
export interface BlobResource {
10+
name: string
11+
blob: Blob
12+
}
13+
14+
function isBlobResource(resource: Resource): resource is BlobResource {
15+
return (resource as BlobResource).blob instanceof Blob
16+
}
17+
18+
export type Resource = UrlResource | BlobResource
19+
20+
interface OptionsBase {
1121
resources: Resource[]
1222
concurrency?: number
1323
onProgress?: (index: number) => Promise<void>
1424
}
1525

16-
export default async function downloader(options: Options): Promise<void> {
26+
export interface SaveOptions extends OptionsBase {
27+
filename: string
28+
}
29+
30+
function isSaveOptions(options: Options): options is SaveOptions {
31+
return 'filename' in options
32+
}
33+
34+
export interface ZipOptions extends OptionsBase { }
35+
36+
export type Options = ZipOptions | SaveOptions
37+
38+
export default async function downloader(options: SaveOptions): Promise<void>
39+
export default async function downloader(options: ZipOptions): Promise<Blob>
40+
export default async function downloader(options: Options): Promise<void | Blob> {
1741
const writer = new ZipWriter(new BlobWriter('application/zip'))
1842
const limit = pLimit(options.concurrency || 10)
1943
await Promise.all(options.resources.map((resource, index) => limit(async () => {
2044
await options.onProgress?.(index)
21-
return writer.add(resource.name, new HttpReader(resource.url))
45+
const reader = isBlobResource(resource)
46+
? new BlobReader(resource.blob)
47+
: new HttpReader(resource.url)
48+
return writer.add(resource.name, reader)
2249
})))
2350
const blob = await writer.close()
24-
const url = URL.createObjectURL(blob)
25-
GM_download(url, options.filename)
51+
if (!isSaveOptions(options)) {
52+
return blob
53+
}
54+
GM_download(URL.createObjectURL(blob), options.filename)
2655
}

dist/downloader.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6624,17 +6624,41 @@ var __privateWrapper = (obj, member, setter, getter) => ({
66246624
throw new TypeError("Expected `concurrency` to be a number from 1 and up");
66256625
}
66266626
}
6627+
function isBlobResource(resource) {
6628+
return resource.blob instanceof Blob;
6629+
}
6630+
function isSaveOptions(options) {
6631+
return "filename" in options;
6632+
}
66276633
async function downloader2(options) {
66286634
const writer = new ZipWriter(new BlobWriter("application/zip"));
66296635
const limit = pLimit(options.concurrency || 10);
66306636
await Promise.all(options.resources.map((resource, index) => limit(async () => {
66316637
var _a;
66326638
await ((_a = options.onProgress) == null ? void 0 : _a.call(options, index));
6633-
return writer.add(resource.name, new HttpReader(resource.url));
6639+
const reader = isBlobResource(resource) ? new BlobReader(resource.blob) : new HttpReader(resource.url);
6640+
return writer.add(resource.name, reader);
66346641
})));
66356642
const blob = await writer.close();
6636-
const url = URL.createObjectURL(blob);
6637-
GM_download(url, options.filename);
6638-
}
6643+
if (!isSaveOptions(options)) {
6644+
return blob;
6645+
}
6646+
GM_download(URL.createObjectURL(blob), options.filename);
6647+
}
6648+
(async () => {
6649+
await downloader2({
6650+
resources: [
6651+
{ name: "index.html", url: location.href },
6652+
{
6653+
name: "hello.txt",
6654+
blob: new Blob(["hello world"], { type: "text/plain" })
6655+
}
6656+
],
6657+
concurrency: 10,
6658+
async onProgress(index) {
6659+
console.log(`正在下载第 ${index + 1} 个资源`);
6660+
}
6661+
});
6662+
})();
66396663
return downloader2;
66406664
}();

0 commit comments

Comments
 (0)