基础强化方法推荐
简介
目前提供两个方法:
openFile
:打开文件downloadFile
:下载文件
如果使用浏览器原生的方案,会导致插件在选择文件或下载文件时,插件页面被隐藏,使用上面的两个方法,插件页面就不会失焦。
使用方法
openFile
此方法可以通过api的形式选择一个文件。例如,我要选择一张图片,并在图片文件夹
中
typescript
window.preload.openFile({
title: '请选择一张图片',
// 图片文件夹
defaultPath: utools.getPath('Pictures'),
buttonLabel: '选择',
// 约束拓展名
filters: [{
name: '图片',
// 约束拓展名为图片
extensions: ['jpg', 'jpeg', 'png', 'gif', 'webp']
}]
}).then(file => {
// file为File对象
}).catch(e => {
console.error("打开图片失败", e);
})
downloadFile
此方法可以把文件、链接、文字、base64格式的图片保存到本地。
- 将一个base64格式的图片保存到本地
typescript
const base64 = 'data:image/png;base64,AAAAAAAAA==....'
window.preload.downloadFile(base64, '图片.png').then(path => {
console.log('图片保存成功,保存到:', path);
});
- 将一段文字保存到本地
typescript
const text = '测试问题'
const base64 = `data:text/plain;base64,${btoa(text)}`;
window.preload.downloadFile(base64, 'test.text').then(path => {
console.log('文本保存成功,保存到:', path);
});
- 将一个文件保存到本地
typescript
// 此处为接收到的文件对象
const file = new File();
window.preload.downloadFile(file, 'a.exe').then(path => {
console.log('文件保存成功,保存到:', path);
});
使用前提
新建preload.js
文件,并在plugin.json
中指定preload.js
json
{
"preload": "preload.js"
}
之后再preload.js中粘贴下面代码
preload.js
preload.js
javascript
const {readFile} = require('node:fs');
const {basename} = require('node:path');
const {URL} = require("node:url");
const https = require("node:https");
const http = require("node:http");
/**
* 获取一个文件
* @param options {options: {
* title?: string,
* defaultPath?: string,
* buttonLabel?: string,
* filters?: { name: string, extensions: string[] }[],
* properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory' | 'dontAddToRecent'>,
* message?: string,
* securityScopedBookmarks?: boolean
* }} 参数
* @return {Promise<File>} 返回blob对象
*/
function openFile(options) {
return new Promise((resolve, reject) => {
const paths = utools.showOpenDialog(options);
const path = paths[0];
if (path) {
readFile(path, (err, data) => {
if (err) {
reject(err);
return;
}
const blob = new Blob([data], {type: 'application/octet-stream'});
resolve(new File([blob], basename(path)));
})
}
})
}
/**
* 从url下载一个文件
* @param url 文件地址
* @param path 保存的地址
* @return {Promise<void>}
*/
function downloadFileFromUrl(url, path) {
const file = fs.createWriteStream(path);
const link = new URL(url);
return new Promise((resolve, reject) => {
file.on('finish', function () {
file.close();
resolve();
}).on('error', e => {
file.close();
reject(e);
});
(link.protocol.startsWith("https") ? https : http).get(link, (response) => {
response.pipe(file);
}).on('error', (error) => {
reject(error);
}).end();
})
}
/**
* 下载一个文件
* @param data {string | Blob | ArrayBuffer} 文件内容,可以使blob(file)或ArrayBuffer或者链接或者DATA URL
* @param name {string} 文件名
* @return {Promise<string>};
*/
async function downloadFile(data, name) {
const target = utools.showSaveDialog({
title: '请选择文件保存位置',
buttonLabel: '保存',
defaultPath: path.join(utools.getPath('downloads'), name),
properties: ['createDirectory']
});
if (!target) {
return Promise.reject(new Error("请选择文件保存位置"))
}
return new Promise(async (resolve, reject) => {
if (data instanceof ArrayBuffer) {
fs.writeFile(target, new Uint8Array(data), e => {
if (e) {
return reject(e)
}
resolve(target);
});
} else if (data instanceof Blob) {
const ab = await data.arrayBuffer();
fs.writeFile(target, new Uint8Array(ab), e => {
if (e) {
return reject(e)
}
resolve(target);
});
} else {
// 如果是链接
if (/^https?:\/\//.test(data)) {
return downloadFileFromUrl(data, target)
.then(() => resolve(target))
.catch(reject);
} else if (/^data:(.*?);base64,/.test(data)) {
// 数据URL
let byteCharacters = atob(
data.replace(/^data:(.*?);base64,/, "")
);
let byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
fs.writeFile(target, byteArray, e => {
if (e) {
return reject(e)
}
resolve(target);
});
} else {
reject(new Error("文件内容未知"))
}
}
})
}
window.preload = {
openFile, downloadFileFromUrl, downloadFile
}
vite-env.d.ts
如果您使用vite开发,可以将下面内容粘贴到vite-env.d.ts
,如果您不是vite开发,可以在项目文件夹下创建文件index.d.ts
,将下面内容粘贴到文件内,即可获得代码提示。
vite-env.d.ts
typescript
interface OpenFileOption {
title?: string,
defaultPath?: string,
buttonLabel?: string,
filters?: { name: string, extensions: string[] }[],
properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory' | 'dontAddToRecent'>,
message?: string,
securityScopedBookmarks?: boolean
}
interface Window {
preload: {
/**
* 打开一个文件,并返回File对象
* @param options 参数
* @return 返回File对象
*/
openFile(options: OpenFileOption): Promise<File>,
/**
* 从url下载一个文件到指定目录
* @param url 链接
* @param path 要保存的文件路径,包含文件名
*/
downloadFileFromUrl(url: string, path: string): Promise<void>,
/**
* 下载一个文件
* @param data 文件内容,可以使blob(file)或ArrayBuffer或者链接或者DATA URL
* @param name 文件名
* @return 文件保存的路径
*/
downloadFile(data: string | Blob | ArrayBuffer, name: string): Promise<string>
}
}