This commit is contained in:
2025-05-30 21:36:12 +08:00
parent f084492ed9
commit 7e167fd4a1
33 changed files with 2019 additions and 5 deletions

View File

@@ -0,0 +1,23 @@
/**
* 过滤文件, 过滤 .DS_Store, node_modules, 以.开头的文件, 过滤 __开头的文件
* @param files
* @returns
*/
export const filterFiles = (files: File[]) => {
files = files.filter((file) => {
if (file.webkitRelativePath.startsWith('__MACOSX')) {
return false;
}
// 过滤node_modules
if (file.webkitRelativePath.includes('node_modules')) {
return false;
}
// 过滤文件 .DS_Store
if (file.name === '.DS_Store') {
return false;
}
// 过滤以.开头的文件
return !file.name.startsWith('.');
});
return files;
};

View File

@@ -0,0 +1,3 @@
export * from './to-file.ts';
export * from './filter-files.ts';
export * from './random-id.ts';

View File

@@ -0,0 +1,3 @@
export const randomId = () => {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};

View File

@@ -0,0 +1,105 @@
const getFileExtension = (filename: string) => {
return filename.split('.').pop();
};
const getFileType = (extension: string) => {
switch (extension) {
case 'js':
return 'text/javascript';
case 'css':
return 'text/css';
case 'html':
return 'text/html';
case 'json':
return 'application/json';
case 'png':
return 'image/png';
case 'jpg':
return 'image/jpeg';
case 'jpeg':
return 'image/jpeg';
case 'gif':
return 'image/gif';
case 'svg':
return 'image/svg+xml';
case 'webp':
return 'image/webp';
case 'ico':
return 'image/x-icon';
default:
return 'text/plain';
}
};
const checkIsBase64 = (content: string) => {
return content.startsWith('data:');
};
/**
* 获取文件的目录和文件名
* @param filename 文件名
* @returns 目录和文件名
*/
export const getDirectoryAndName = (filename: string) => {
if (!filename) {
return null;
}
if (filename.startsWith('.')) {
return null;
} else {
filename = filename.replace(/^\/+/, ''); // Remove all leading slashes
}
const hasDirectory = filename.includes('/');
if (!hasDirectory) {
return { directory: '', name: filename };
}
const parts = filename.split('/');
const name = parts.pop()!; // Get the last part as the file name
const directory = parts.join('/'); // Join the remaining parts as the directory
return { directory, name };
};
/**
* 把字符串转为文件流并返回文件流根据filename的扩展名自动设置文件类型.
* 当不是文本类型自动需要把base64的字符串转为blob
* @param content 字符串
* @param filename 文件名
* @returns 文件流
*/
export const toFile = (content: string, filename: string) => {
// 如果文件名是 a/d/a.js 格式的则需要把d作为目录a.js作为文件名
const directoryAndName = getDirectoryAndName(filename);
if (!directoryAndName) {
throw new Error('Invalid filename');
}
const { name } = directoryAndName;
const extension = getFileExtension(name);
if (!extension) {
throw new Error('Invalid filename');
}
const isBase64 = checkIsBase64(content);
const type = getFileType(extension);
if (isBase64) {
// Decode base64 string
const base64Data = content.split(',')[1]; // Remove the data URL prefix
const byteCharacters = atob(base64Data);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], { type });
return new File([blob], filename, { type });
} else {
const blob = new Blob([content], { type });
return new File([blob], filename, { type });
}
};
/**
* 把字符串转为文本文件
* @param content 字符串
* @param filename 文件名
* @returns 文件流
*/
export const toTextFile = (content: string = 'keep directory exist', filename: string = 'keep.txt') => {
const file = toFile(content, filename);
return file;
};