import { useState } from "react"; import * as tus from "tus-js-client"; import { env } from "../env"; import { getCompressedImageUrl } from "@nice/utils"; interface UploadResult { compressedUrl: string; url: string; fileId: string; fileName: string; } export function useTusUpload() { const [uploadProgress, setUploadProgress] = useState< Record >({}); const [isUploading, setIsUploading] = useState(false); const [uploadError, setUploadError] = useState(null); const getFileId = (url: string) => { const parts = url.split("/"); const uploadIndex = parts.findIndex((part) => part === "upload"); if (uploadIndex === -1 || uploadIndex + 4 >= parts.length) { throw new Error("Invalid upload URL format"); } return parts.slice(uploadIndex + 1, uploadIndex + 5).join("/"); }; const getResourceUrl = (url: string) => { const parts = url.split("/"); const uploadIndex = parts.findIndex((part) => part === "upload"); if (uploadIndex === -1 || uploadIndex + 4 >= parts.length) { throw new Error("Invalid upload URL format"); } const resUrl = `http://${env.SERVER_IP}:${env.FILE_PORT}/uploads/${parts.slice(uploadIndex + 1, uploadIndex + 6).join("/")}`; return resUrl; }; const handleFileUpload = async ( file: File | Blob, onSuccess: (result: UploadResult) => void, onError: (error: Error) => void, fileKey: string // 添加文件唯一标识 ) => { // console.log() setIsUploading(true); setUploadProgress((prev) => ({ ...prev, [fileKey]: 0 })); setUploadError(null); try { // 如果是Blob,需要转换为File let fileName = "uploaded-file"; if (file instanceof Blob && !(file instanceof File)) { // 根据MIME类型设置文件扩展名 const extension = file.type.split('/')[1]; fileName = `uploaded-file.${extension}`; } const uploadFile = file instanceof Blob && !(file instanceof File) ? new File([file], fileName, { type: file.type }) : file as File; console.log(`http://${env.SERVER_IP}:${env.SERVER_PORT}/upload`); const upload = new tus.Upload(uploadFile, { endpoint: `http://${env.SERVER_IP}:${env.SERVER_PORT}/upload`, retryDelays: [0, 1000, 3000, 5000], metadata: { filename: uploadFile.name, filetype: uploadFile.type, size: uploadFile.size as any, }, onProgress: (bytesUploaded, bytesTotal) => { const progress = Number( ((bytesUploaded / bytesTotal) * 100).toFixed(2) ); setUploadProgress((prev) => ({ ...prev, [fileKey]: progress, })); }, onSuccess: async (payload) => { if (upload.url) { const fileId = getFileId(upload.url); //console.log(fileId) const url = getResourceUrl(upload.url); setIsUploading(false); setUploadProgress((prev) => ({ ...prev, [fileKey]: 100, })); onSuccess({ compressedUrl: getCompressedImageUrl(url), url, fileId, fileName: uploadFile.name, }); } }, onError: (error) => { const err = error instanceof Error ? error : new Error("Unknown error"); setIsUploading(false); setUploadError(error.message); console.log(error); onError(err); }, }); upload.start(); } catch (error) { const err = error instanceof Error ? error : new Error("Upload failed"); setIsUploading(false); setUploadError(err.message); onError(err); } }; return { uploadProgress, isUploading, uploadError, handleFileUpload, }; }