2025-05-06 17:35:40 +08:00
|
|
|
|
/**
|
|
|
|
|
* 文件下载
|
|
|
|
|
* *将实时创建<a>标签并在下载完成后自动移除
|
|
|
|
|
* @param url 文件地址
|
|
|
|
|
* @param name 文件名
|
|
|
|
|
*/
|
|
|
|
|
export function downloadFile(url: string, name?: string): void {
|
|
|
|
|
if (!url) return;
|
|
|
|
|
const element = document.createElement('a');
|
|
|
|
|
element.href = url;
|
|
|
|
|
if (name) {
|
|
|
|
|
element.download = name;
|
|
|
|
|
}
|
|
|
|
|
element.click();
|
|
|
|
|
element.remove();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 文件选择
|
|
|
|
|
* @param accept 支持的文件类型
|
|
|
|
|
* @param limit 文件大小限制(byte)
|
|
|
|
|
* @returns 选中的文件域
|
|
|
|
|
*/
|
|
|
|
|
export async function selectFile(accept?: string, limit?: number): Promise<File | void> {
|
|
|
|
|
const element = document.createElement('input');
|
|
|
|
|
element.type = 'file';
|
|
|
|
|
element.accept = accept ?? '';
|
|
|
|
|
try {
|
|
|
|
|
return await new Promise<File | void>((resolve, reject) => {
|
|
|
|
|
element.onchange = () => {
|
|
|
|
|
const file = element.files?.[0];
|
|
|
|
|
if (!file?.size) return resolve();
|
|
|
|
|
if (limit && limit < file.size) return reject(`文件大小不能超过${~~(limit / 1000)}KB`);
|
|
|
|
|
const extension = file.name.split('.').pop()!.toLowerCase();
|
|
|
|
|
if (accept && !accept.toLowerCase().includes(extension)) return reject(`仅支持${accept}文件`);
|
|
|
|
|
resolve(file);
|
|
|
|
|
};
|
|
|
|
|
element.oncancel = () => resolve();
|
|
|
|
|
element.click();
|
|
|
|
|
});
|
|
|
|
|
} finally {
|
|
|
|
|
element.onchange = null;
|
|
|
|
|
element.oncancel = null;
|
|
|
|
|
element.remove();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Base64图片转二进制
|
|
|
|
|
* @param base64:Base64 图片数据
|
|
|
|
|
* @returns 二进制数据
|
|
|
|
|
*/
|
|
|
|
|
export function base64ToBlob(base64: string): Blob | undefined {
|
|
|
|
|
const [prefix, data] = base64?.split('base64,', 2) ?? [];
|
|
|
|
|
const type = prefix?.match(/:(.*?);/)?.[1];
|
|
|
|
|
const str = atob(data ?? '');
|
|
|
|
|
if (!type || !str?.length) return;
|
|
|
|
|
let n = str.length;
|
|
|
|
|
const buffer = new Uint8Array(n);
|
|
|
|
|
while (n--) {
|
|
|
|
|
buffer[n] = str.charCodeAt(n);
|
|
|
|
|
}
|
|
|
|
|
return new Blob([buffer], { type });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 文本转二进制
|
|
|
|
|
* @param text 文本字符
|
|
|
|
|
* @returns 二进制数据
|
|
|
|
|
*/
|
|
|
|
|
export function textToBlob(text: string): Blob | undefined {
|
|
|
|
|
if (!text.length) return;
|
|
|
|
|
return new Blob([text], { type: 'text/plain' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 文本文件解码
|
|
|
|
|
* @param file 文件域
|
|
|
|
|
* @returns 文本字符串
|
|
|
|
|
*/
|
|
|
|
|
export async function decodeTextFile(file: File): Promise<string | undefined> {
|
|
|
|
|
if (!file.size) return;
|
|
|
|
|
const decoder = new TextDecoder();
|
|
|
|
|
const buffer = await file.arrayBuffer();
|
|
|
|
|
return decoder.decode(buffer);
|
|
|
|
|
}
|