deotalandAi/packages/utils/src/servers/fileserver.js

161 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { requestUtils,clientApi } from "../index";
let urlRule = 'https://api.deotaland.aiIMGURL'
export class FileServer {
//文件上传缓存映射 - 静态属性,所有实例共享
static fileCacheMap = new Map();
constructor() {
}
//文件拼接
concatUrl(url) {
return urlRule.replace('IMGURL',url)
}
/**
* 从URL中提取有效的文件名
* @param {*} url 文件URL
* @returns 有效的文件名
*/
extractFileName(url) {
// 如果是base64格式根据MIME类型生成文件名
if (url.startsWith('data:')) {
const mimeType = url.match(/data:([^;]+)/)?.[1];
const extension = this.getExtensionFromMimeType(mimeType);
return `uploaded_file_${Date.now()}.${extension}`;
}
// 如果是普通URL提取文件名并清理
try {
const urlObj = new URL(url);
const pathname = urlObj.pathname;
const fileName = pathname.split('/').pop() || 'uploaded_file';
// 移除查询参数和哈希
const cleanFileName = fileName.split('?')[0].split('#')[0];
// 如果没有扩展名尝试从URL路径推断
if (!cleanFileName.includes('.')) {
const extension = this.inferExtensionFromPath(pathname);
return cleanFileName + (extension ? `.${extension}` : '');
}
return cleanFileName || `uploaded_file_${Date.now()}`;
} catch (error) {
// URL解析失败使用默认文件名
return `uploaded_file_${Date.now()}`;
}
}
/**
* 从MIME类型获取文件扩展名
*/
getExtensionFromMimeType(mimeType) {
const mimeMap = {
'image/jpeg': 'jpg',
'image/jpg': 'jpg',
'image/png': 'png',
'image/gif': 'gif',
'image/bmp': 'bmp',
'image/webp': 'webp',
'image/svg+xml': 'svg',
'application/pdf': 'pdf',
'text/plain': 'txt',
'application/json': 'json'
};
return mimeMap[mimeType] || 'bin';
}
/**
* 从URL路径推断文件扩展名
*/
inferExtensionFromPath(pathname) {
// 常见的图片路径模式
if (pathname.includes('/image/') || pathname.includes('/img/')) return 'jpg';
if (pathname.includes('/photo/')) return 'jpg';
if (pathname.includes('/picture/')) return 'png';
return null;
}
//轮询获取并发时的线上文件映射
async pollFileCacheMap(cacheKey) {
return new Promise((resolve, reject) => {
const interval = setInterval(() => {
if (FileServer.fileCacheMap.get(cacheKey)!='loading') {
clearInterval(interval);
resolve(FileServer.fileCacheMap.get(cacheKey));
}
}, 1000); // 每1秒检查一次
});
}
//上传文件
async uploadFile(url) {
const cacheKey = url.slice(-8);
return new Promise(async (resolve, reject) => {
if(FileServer.fileCacheMap.has(cacheKey)&&FileServer.fileCacheMap.get(cacheKey)!='loading'){
resolve(this.concatUrl(FileServer.fileCacheMap.get(cacheKey)));
return;
}
if(FileServer.fileCacheMap.get(cacheKey)=='loading'){
const loadUrl = await this.pollFileCacheMap(cacheKey);
resolve(this.concatUrl(loadUrl));
return;
}
FileServer.fileCacheMap.set(cacheKey,'loading');
const file = await this.fileToBlob(url);//将文件或者base64文件转为blob对象
const formData = new FormData();
// 从URL中提取文件名如果没有则使用默认文件名
const fileName = this.extractFileName(url);
formData.append('file', file, fileName);
try {
const response = await requestUtils.upload(clientApi.default.UPLOAD.url, formData);
if(response.code==0){
let data = response.data;
if(data.url){
// 截取后八位作为缓存 key
FileServer.fileCacheMap.set(cacheKey, data.url);
resolve(urlRule.replace('IMGURL',data.url));
}
}
} catch (error) {
reject(error);
console.error('上传文件失败:', error);
throw error;
}
})
}
//文件文件或者base64文件转为blob对象
fileToBlob(fileOrBase64) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', fileOrBase64);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(new Error('文件转换失败'));
}
};
xhr.onerror = reject;
xhr.send();
});
}
//本地文件或者oss文件转为base64格式
async fileToBase64(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
const reader = new FileReader();
reader.readAsDataURL(xhr.response);
reader.onloadend = () => {
resolve(reader.result);
};
} else {
reject(new Error('文件转换失败'));
}
};
xhr.onerror = reject;
xhr.send();
});
}
}