





















import { useState } from 'react';
import { message } from 'antd';
import SparkMD5 from 'spark-md5';
import { uploadFile as uploadFileService, uploadInit, finishUpload } from '@/services/files';
interface UploadParams {
md5: string;
file_name: string;
file_size: number;
part_size: number;
}
const useUpload = () => {
const [uploading, setUploading] = useState(false);
const [progress, setProgress] = useState(0);
const calculateMD5 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const chunkSize = 2097152; // 2MB
const chunks = Math.ceil(file.size / chunkSize);
const spark = new SparkMD5.ArrayBuffer();
const fileReader = new FileReader();
let currentChunk = 0;
fileReader.onload = (e) => {
if (e.target?.result) {
spark.append(e.target.result as ArrayBuffer);
currentChunk++;
if (currentChunk < chunks) {
loadNext();
} else {
resolve(spark.end());
}
}
};
fileReader.onerror = reject;
const loadNext = () => {
const start = currentChunk * chunkSize;
const end = start + chunkSize >= file.size ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(file.slice(start, end));
};
loadNext();
});
};
const uploadFile = async (file: File, basePath: string = 'data') => {
try {
setUploading(true);
setProgress(0);
// 使用新的简单上传接口
setProgress(30);
const result = await uploadFileService(file, basePath);
if (result.code === 200 && result.data?.success) {
setProgress(100);
return result.data.file_id;
} else {
throw new Error(result.message || '上传失败');
}
} catch (error: any) {
console.error('文件上传失败:', error);
const errorMessage = error?.response?.data?.detail || error?.message || '上传失败,请重试';
message.error(errorMessage);
throw error;
} finally {
setUploading(false);
}
};
const uploadWholeFile = async (file: File, uploadUrl: string) => {
const response = await fetch(uploadUrl, {
method: 'PUT',
headers: {
'Content-Type': 'application/octet-stream',
},
body: file,
});
if (!response.ok) {
throw new Error(`上传失败: ${response.statusText}`);
}
setProgress(90);
};
const downloadFile = async (fileId?: any) => {
const res = await getFilesDownload(fileId);
const response = res?.data?.url;
if(res.code === 200){
const contentDisposition = response.headers['content-disposition'];
let fileName = 'cargo_export'; // 默认文件名
if (contentDisposition) {
// 关键正则:兼容带/不带引号、URL编码的文件名
const match = contentDisposition.match(/filename=(?:")?(.+?)(?:")?(?:;|$)/i);
if (match && match[1]) {
fileName = decodeURIComponent(match[1].trim()); // 解码+去空格
}
}
console.log(response);
try {
const downloadElement = document.createElement("a");
const href = window.URL.createObjectURL(response?.data); // 直接使用Blob对象
downloadElement.style.display = "none";
downloadElement.href = href;
// 优先使用传入的fileName,否则默认名
downloadElement.download = fileName || 'download file';
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href); // 释放资源
} catch (error) {
console.error("下载文件时出错:", error);
throw new Error("文件下载失败,请重试"); // 抛出错误供上层处理
}
}
};
const exportFile = async (fileId: any, fileName: string) => {
const res = await getArchivalData(fileId);
const response = res?.data;
if(res.code === 200){
const url = response;
const a = document.createElement('a');
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // Clean up the URL object
}
};
// 导出结构化数据
const exportStructuredData = async (fileId: any, fileName: string) => {
const res = await getStructuredDataExport(fileId);
const response = res?.data;
if(res.code === 200){
const url = response;
const a = document.createElement('a');
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // Clean up the URL object
}
};
return { uploading, progress, uploadFile, downloadFile, exportFile, exportStructuredData };
};
export default useUpload;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。