自定义hook的写法

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;
 
 
----------------------------------
自定义hook的消费
  const { uploadFile } = useUpload();

posted on 2026-04-25 17:28  漫思  阅读(11)  评论(0)    收藏  举报

导航