PageSourceSearch

https://lingyuzhao.top/js/utils_io.js

js lingyuzhao.top collected 2026-10-06 13:16:14 UTC 6,588 bytes, 156 lines download raw bytes

1class Utils_io {
2
3    /**
4     * 将一个 url 解析为图片 并将下载操作绑定到一个元素中,通常我们会用于进行某些特定内容的下载操作
5     * @param element{Element[]|NodeListOf<Element>} 需要被做为点击即下载的元素 如果是 a 标签,则会直接将此元素做为下载的元素 而不会额外创建!
6     * @param url{string} 元素的 url
7     * @param filename{string} 文件名
8     * @param jokerPopup{JokerBox_popUp} 下载完毕或下载出错的状态弹窗
9     * @param mobileDownloadFun  如果检测到 是 移动端下载,则可能 base 的方式不被支持,会优先调用此操作,这里将返回一个 包含 url 的 a 标签 和 url 对应文件的 blob 对象
10     */
11    static downloadImageDataAsFile(element,
12                                   url,
13                                   filename,
14                                   jokerPopup,
15                                   mobileDownloadFun = (a, _) => a.click()) {
16        // 解析Data URL
17        const parts = url.split(',');
18        if (parts.length !== 2) {
19            console.error('Invalid data URL', url);
20            jokerPopup.show("无效的下载链接");
21            return;
22        }
23        const base64Data = parts[1];
24
25        // 检查Base64数据是否有效
26        if (base64Data.length === 0) {
27            console.error('Empty Base64 data');
28            jokerPopup.show("下载链接为空");
29            return;
30        }
31
32        try {
33            const byteString = atob(base64Data);
34            const arrayBuffer = new ArrayBuffer(byteString.length);
35            const uint8Array = new Uint8Array(arrayBuffer);
36            for (let i = 0; i < byteString.length; i++) {
37                uint8Array[i] = byteString.charCodeAt(i);
38            }
39
40            // 假设图片是JPEG格式的,您可能需要根据实际情况修改这个MIME类型
41            const blob = new Blob([uint8Array], {type: 'image/png'});
42
43            const link = document.createElement('a');
44            link.href = window.URL.createObjectURL(blob);
45            link.download = filename;
46
47            for (let htmlElement of element) {
48                if (htmlElement.tagName === 'A') {
49                    htmlElement.href = link.href;
50                    htmlElement.download = link.download;
51                    continue;
52                }
53                htmlElement.addEventListener('click', function (e) {
54                    try {
55                        if (isMobileDevice() && mobileDownloadFun) {
56                            mobileDownloadFun(link, blob);
57                            jokerPopup.show("开始下载啦!")
58                            return;
59                        }
60                        link.click();
61                        jokerPopup.show(filename + " 开始下载...")
62                    } catch (e) {
63                        jokerPopup.show("下载失败,您可以尝试长按/右键图片下载!!");
64                    }
65                });
66            }
67        } catch (error) {
68            console.error('Error decoding Base64 data:', error);
69            jokerPopup.show("下载失败");
70        }
71    }
72
73    /**
74     *
75     * @param fileObject 需要被解析的文件对象
76     * @param handleFile 文件对象的处理函数 输入的是 当前文件数量 文件对象 和 文件路径  以及一个标记位 当您在回调函数中将标记位的0索引值设置为 true 才会继续执行下一个
77     * @param endCallback 解压完毕的回调函数 输入的是上传完毕的文件对象
78     * @returns {Promise<void>} 无返回
79     */
80    static async unzipFile(fileObject, handleFile, endCallback = (f) => {
81    }) {
82        // Create a new JSZip instance
83        const zip = new JSZip();
84
85        // 进行一个标记 代表上一个处理是否完毕
86        let backOk = [true];
87        let length = 0;
88
89        let c = 0;
90        let layer_c = 0;
91
92        // Load the zip file from the provided file object
93        zip.loadAsync(fileObject).then(
94            d => {
95                {
96                    for (const fileName in d.files) {
97                        length++;
98                    }
99                }
100                console.info(length)
101                traverseDirectory(d, '', endCallback);
102            }
103        )
104
105
106        /**
107         * 遍历目录
108         * @param directory
109         * @param pathPrefix
110         * @param endCallback {function}
111         */
112        function traverseDirectory(directory, pathPrefix = '', endCallback = null) {
113
114            for (const fileName in directory.files) {
115                const filePath = `${pathPrefix}/${fileName}`;
116                const entry = directory.files[fileName];
117
118                if (entry.dir) { // If it's a directory, traverse further
119                    traverseDirectory(entry, filePath);
120                    ++layer_c;
121                } else { // If it's a file, pass the file and path to the handler function
122                    entry.async('blob').then(
123                        blob => {
124                            // 如果上一个文件/文件目录没有处理完毕 就在这里等一会
125                            const timeout = setInterval(() => {
126                                if (backOk[0]) {
127                                    // 当上一个处理完毕了再处理当前的
128                                    backOk[0] = false;
129                                    handleFile(++c, blob, filePath, backOk);
130                                    clearInterval(timeout);
131                                    if (endCallback) {
132                                        ++layer_c;
133                                    }
134                                }
135                            }, 1000);
136                        }
137                    ).catch(
138                        error => {
139                            console.error(`Error processing file ${filePath}:`, error)
140                        }
141                    )
142                }
143            }
144
145            if (endCallback !== null) {
146                // 设置一个定时器 判断当前是否已经处理完毕
147                const interval = setInterval(() => {
148                    if (layer_c === length) {
149                        endCallback(fileObject);
150                        clearInterval(interval)
151                    }
152                }, 1000);
153            }
154        }
155    }
156}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.