UNPKG

z-util-page

Version:
367 lines (366 loc) 10.9 kB
"use strict"; /** * @module FileHelper * @category 文件操作辅助类 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.choose = choose; exports.save = save; exports.read = read; exports.saveFileToDir = saveFileToDir; exports.pickDir = pickDir; const tslib_1 = require("tslib"); const index_1 = require("../helper/index"); const index_2 = require("../debounce/index"); /** * 文件选择 * @example * ```ts * choose({ * accept: [".doc",".docx","application/msword"], * capture: "user", * multiple: true * }).then(files => { * console.log(files); * }) * .catch(err => { * console.error(err); * }); * ``` * @param options 文件选择配置 * @param options.accept 以逗号为分隔的[唯一文件类型说明符]列表 * @param options.capture 尝试请求使用设备的媒体捕获设备(如:摄像机),而不是请求一个文件输入。camera–照相机;camcorder–摄像机;microphone–录音 * @param options.multiple 是否允许多选 */ function choose(options = {}) { return new Promise((resolve, reject) => { const input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('accept', (options.accept || []).join(',')); input.setAttribute('capture', options.capture || ''); if (options.multiple) input.setAttribute('multiple', 'true'); input.addEventListener('change', function (e) { if (input.files) resolve(input.files); }); (0, index_1.clickElement)(input); }); } /** * H5文件下载方法 * @example * ```ts * save(new Blob(['你好世界'], { type: 'text/plain' }), 'test.txt'); * save('https://www.baidu.com/img/flexible/logo/pc/result@2.png', 'baidu.png'); * ``` * @param file 资源链接或者blob对象 * @param saveFileName 保存文件名 */ function save(file, saveFileName = '') { let url = ''; if (typeof file === 'string') { url = file; } else { try { url = URL.createObjectURL(file); } catch (error) { console.log(error); } } let alink = document.createElement('a'); alink.href = url; alink.download = saveFileName || ''; alink.style.display = 'none'; alink.target = "_blank"; document.body.appendChild(alink); (0, index_1.clickElement)(alink); document.body.removeChild(alink); } class FileReaderDecorate { constructor(file) { Object.defineProperty(this, "reader", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "file", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.reader = new FileReader(); this.file = file; } //读取操作发生中断时触发 abort(fun) { this.reader.addEventListener('abort', () => { fun(this.reader); }); return this; } //读取操作发生错误时触发 error(fun) { this.reader.addEventListener('error', () => { fun(this.reader.error); }); return this; } //读取操作完成时触发 load(fun) { this.reader.addEventListener('load', () => { fun(this.reader); }); return this; } //读取操作开始时触发 loadstart(fun) { this.reader.addEventListener('loadstart', () => { fun(this.reader); }); return this; } //读取操作结束时(要么成功,要么失败)触发 loadend(fun) { this.reader.addEventListener('loadend', () => { fun(this.reader.result); }); return this; } //读取操作结束时(要么成功,要么失败)触发。 loadendPromise() { return new Promise((resolve, reject) => { this.reader.addEventListener('loadend', () => { resolve(this.reader.result); }); this.reader.addEventListener('error', () => { reject(this.reader.error); }); }); } //在读取Blob时触发。 progress(fun) { this.reader.addEventListener('progress', () => { fun(this.reader); }); return this; } getStatus() { return this.reader.readyState; } getResult() { return this.reader.result; } start(type) { try { Reflect.get(this.reader, "readAs" + type).call(this.reader, this.file); } catch (error) { console.error(error); } return this; } stop() { this.reader.abort(); return this; } } /** * 文件读取 * @example * ```ts * const reader = read(file) * .loadend((res) => { * console.log(res); * }) * //start方法参数类型:"ArrayBuffer" | "BinaryString" | "DataURL" | "Text" * .start("ArrayBuffer"); * * //读取操作发生中断时触发 * reader.abort((abo) => { * console.log(abo); * }) * * //读取操作发生错误时触发 * reader.error((err) => { * console.log(err); * }) * * //读取操作完成时触发 * reader.load((res) => { * console.log(res); * }) * * //读取操作开始时触发 * reader.loadstart((res) => { * console.log(res); * }) * * //读取操作结束时(要么成功,要么失败)触发 * reader.loadstart((res) => { * console.log(res); * }) * * //获取读取结果的promise * const promise = reader.loadendPromise(); * * //在读取Blob时触发。 * reader.progress((res) => { * console.log(res); * }) * * //获取状态 * const status = reader.getStatus(); * * //获取结果 * const result = reader.getResult(); * * //中断读取 * reader.stop(); * ``` * @param file File对象或Blob对象 */ function read(file) { return new FileReaderDecorate(file); } const DirMap = new Map(); const warnMessage = (0, index_2.debounce)((err) => { console.warn(err); }, 100); /** * 将文件写入目标文件夹 * @example * ```ts * //需要先调用pickDir选择文件夹 * saveFileToDir('key', 'file.txt', ['string', new Blob(['你好世界'], { type: 'text/plain' })]); * ``` * @param dirKey 文件夹唯一标识,自行定义string,用于后续向同一文件夹写入文件 * @param fileName 文件名 * @param fileContent 二进制文件流或字符串数组 * @param overwrite 是否覆盖同名文件 * @returns { success: boolean, message: string } */ function saveFileToDir(dirKey_1, fileName_1, fileContent_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (dirKey, fileName, fileContent, overwrite = true) { var _a, fileContent_2, fileContent_2_1; var _b, e_1, _c, _d; try { let dirHandlePromise = DirMap.get(dirKey); if (!dirHandlePromise) throw new Error("请先选择文件夹"); const dirHandle = yield dirHandlePromise; // const list = []; // for await (const key of dirHandle.keys()) { // list.push(key); // } // fileName = getName(list, fileName); const fileHandle = yield dirHandle.getFileHandle(fileName, { create: true }); const writable = yield fileHandle.createWritable(); if (!overwrite) { const file = yield fileHandle.getFile(); const fileContent = yield read(file).start("ArrayBuffer").loadendPromise(); writable.write(fileContent); } try { for (_a = true, fileContent_2 = tslib_1.__asyncValues(fileContent); fileContent_2_1 = yield fileContent_2.next(), _b = fileContent_2_1.done, !_b; _a = true) { _d = fileContent_2_1.value; _a = false; const item = _d; yield writable.write(item); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (!_a && !_b && (_c = fileContent_2.return)) yield _c.call(fileContent_2); } finally { if (e_1) throw e_1.error; } } yield writable.close(); return { success: true, message: "保存成功" }; } catch (error) { if (error.code === 20) { DirMap.delete(dirKey); warnMessage(new Error("用户取消选择")); } else { console.error(error); } return { success: false, message: "保存失败" }; } }); } function getName(list, name, index = 1) { console.log(name); const res = list.find(item => item === name); if (res) { const paths = name.split("."); const newName = [].concat(paths, [`(${index})`], [paths.pop()]).join('.'); return getName(list, newName, ++index); } else { return name; } } /** * 选择文件夹(与saveFileToDir共用缓存) * @example * ```ts * //选择文件夹,将其与key绑定 * pickDir('key'); * //强制重新选择 * pickDir('key', true); * ``` * @param dirKey 文件夹唯一标识,自行定义string,用于后续向同一文件夹写入文件 * @param force 是否强制重新选择 * @returns { success: boolean, message: string, data: FileSystemDirectoryHandle | null } */ function pickDir(dirKey_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (dirKey, force = false) { try { if (!self.showDirectoryPicker) throw new Error("该浏览器不支持showDirectoryPicker"); let dirHandlePromise = DirMap.get(dirKey); if (!dirHandlePromise || force) { dirHandlePromise = self.showDirectoryPicker({ id: dirKey, mode: 'readwrite' }); DirMap.set(dirKey, dirHandlePromise); } const dirHandle = yield dirHandlePromise; return { success: true, data: dirHandle, message: "获取成功" }; } catch (error) { if (error.code === 20) { DirMap.delete(dirKey); warnMessage(new Error("用户取消选择")); } else { console.error(error); } return { success: false, data: null, message: "获取失败" }; } }); }