react antd upload custom request处理多个文件上传

news2024/11/26 21:38:24

react antd upload custom request处理多个文件上传的问题

背景:第一次请求需要请求后端返回aws 一个link,再往link push文件,再调用另一个接口告诉后端已经上传成功,拿到返回值。 再把返回值传给业务api... 多文件上传一直是循环触发custom request,并且文件上传完之后,需要利用websocket实时更改页面文件的状态


  // Upload
  interface BotFile {
    botFileId: string;
    url: string;
    botFileKey: string;
    openaiFileId: string | null;
    type: number;
    fileUId: string;
  }
  const [defaultFileList, setDefaultFileList] = useState([]);
  // current uploaded file (antd Upload OnChange)
  const [currentUploadFileList, setCurrentUploadFileList] = useState<RcFile[]>([]);
  // aws completed upload files
  const [uploadedFileList, setUploadedFileList] = useState<BotFile[]>([]);
  const uploadFilesProps = (type: any) => {
    const allowedFileTypes = [
      '.txt',
      '.docx',
      '.pdf',
      '.md',
      '.csv',
      '.json',
      '.xlsx',
      '.xls',
      '.jpg',
      '.jpeg',
      '.png',
    ];
    const maxTotalSize = 500 * 1024 * 1024;
    return {
      name: 'file',
      multiple: true,
      listType: 'picture',
      directory: type,
      showUploadList: false,
      action: '/api/sapien-storage/v1/file/frontEndUploads',
      data: { tenantId: currentUser?.tenantId, type: 'LOCAL_FILE' },
      headers: {
        Authorization: `Bearer ${getToken()}`,
        'api-pass-key': getRasKey(),
      },
      fileList: defaultFileList,
      accept: allowedFileTypes.join(','),
      beforeUpload(file: RcFile, fileList2: RcFile[]) {
        setShowCard(true);
        const ext = file.name.slice(((file.name.lastIndexOf('.') - 1) >>> 0) + 1).toLowerCase();
        if (!allowedFileTypes.includes(ext)) {
          message.error(file.name + ' Unsupported file format.');
          return Upload.LIST_IGNORE;
        }
        if (file.size === 0) {
          updateUploadStatus(file, 'error', 'File cannot be empty');
          return Upload.LIST_IGNORE;
        }
        if (ext === '.xlsx' && file.size > 3145728) {
          updateUploadStatus(file, 'error', 'Max 3MB');
          return Upload.LIST_IGNORE;
        } else if (
          (ext === '.jpg' || ext === '.jpeg' || ext === '.png') &&
          file.size > 10 * 1024 * 1024
        ) {
          updateUploadStatus(file, 'error', 'Max 10MB');
          return Upload.LIST_IGNORE;
        } else if (file.size > 52428800) {
          updateUploadStatus(file, 'error', 'Max 50MB');
          return Upload.LIST_IGNORE;
        }

        let currentTotalSize = 0;
        let currentUploadFileSize = 0;
        fileList2.forEach((item) => {
          currentUploadFileSize += item.size || 0;
        });
        defaultFileList.forEach((item) => {
          currentTotalSize += item.size || 0;
        });

        if (currentTotalSize + currentUploadFileSize > maxTotalSize) {
          if (limitMsg) {
            updateUploadStatus(file, 'error', 'Max 500MB');
            setLimitMsg(false);
            setTimeout(() => {
              setLimitMsg(true);
            }, 1000);
          }
          return Upload.LIST_IGNORE;
        }
      },
      onProgress: (progressEvent: any, file: any) => {
        const percent = Math.floor((progressEvent.loaded / progressEvent.total) * 100);
        setUploadStatus((prevStatus) => {
          const newStatus: any = [...prevStatus];
          const fileIndex = newStatus.findIndex((item: any) => item.uid === file.uid);
          if (fileIndex !== -1) {
            newStatus[fileIndex].status = 'uploading';
            newStatus[fileIndex].percent = percent;
          } else {
            newStatus.push({
              uid: file.uid,
              name: file.name,
              status: 'uploading',
              percent: percent,
              size: file.size,
            });
          }
          return newStatus;
        });
      },
      onChange(info: any) {
        if (info.file.status === 'done') {
          if (info.file.response.code === '1001') {
            setPricingPlanContent(info.file.response.message);
            setPricingPlanModalVisible(true);
            setUploadStatus(info.fileList.filter((item: any) => item.uid !== info.file.uid));
          }

          setCurrentUploadFileList((prevList) => [...prevList, info.file]);
        }
        setDefaultFileList(info.fileList);
        if (fileListContainerRef.current) {
          fileListContainerRef.current.scrollTop = fileListContainerRef.current.scrollHeight;
        }
      },
      customRequest(options: any) {
        const { file, onSuccess, onError, onProgress } = options;

        const formData = {
          fileInfos: [
            {
              fileName: file.name,
              contentType: file.type,
              length: file.size.toString(),
            },
          ],
          fileConstants: 'LOCAL_FILE',
        };
        const xhr = new XMLHttpRequest();
        setUploadRequests((prevRequests) => {
          const newRequests = new Map(prevRequests);
          newRequests.set(file.uid, xhr);
          return newRequests;
        });
        xhr.upload.onprogress = (event) => {
          const percent = Math.floor((event.loaded / event.total) * 100);
          onProgress({ percent }, file);
        };

        xhr.onload = () => {
          if (xhr.status < 200 || xhr.status >= 300) {
            onError(new Error('Upload error'));
            setUploadStatus((prevStatus) => {
              const newStatus = prevStatus.map((item: any) => {
                if (item.uid === file.uid) {
                  return { ...item, status: 'error' };
                }
                return item;
              });
              return newStatus;
            });
            return;
          }
          const response = JSON.parse(xhr.responseText);
          const uploadResData = response.data[0];
          const awsUrl = uploadResData.link;

          const awsXhr = new XMLHttpRequest();
          setUploadRequests((prevRequests) => {
            const newRequests = new Map(prevRequests);
            newRequests.set(file.uid, awsXhr);
            return newRequests;
          });
          awsXhr.upload.onprogress = (event) => {
            const percent = Math.floor((event.loaded / event.total) * 100);
            onProgress({ percent }, file);
          };

          awsXhr.onload = () => {
            if (awsXhr.status < 200 || awsXhr.status >= 300) {
              onError(new Error('AWS Upload error'));
              setUploadStatus((prevStatus) => {
                const newStatus = prevStatus.map((item: any) => {
                  if (item.uid === file.uid) {
                    return { ...item, status: 'error' };
                  }
                  return item;
                });
                return newStatus;
              });
              return;
            }
            if (awsXhr.status === 200) {
              const awsCompletesFileUploadXhr = new XMLHttpRequest();

              setUploadRequests((prevRequests) => {
                const newRequests = new Map(prevRequests);
                newRequests.set(file.uid, awsCompletesFileUploadXhr);
                return newRequests;
              });
              const awsCompletesFileUploadFormData = {
                fileInfos: response.data,
                fileConstants: 'LOCAL_FILE',
              };
              awsCompletesFileUploadXhr.upload.onprogress = (event) => {
                const percent = Math.floor((event.loaded / event.total) * 100);
                onProgress({ percent }, file);
              };

              awsCompletesFileUploadXhr.open(
                'POST',
                '/api/sapien-storage/v1/file/awsCompletesFileUpload',
                true,
              );
              awsCompletesFileUploadXhr.onload = () => {
                if (xhr.status < 200 || xhr.status >= 300) {
                  onError(new Error('Upload error'));
                  setUploadStatus((prevStatus) => {
                    const newStatus = prevStatus.map((item: any) => {
                      if (item.uid === file.uid) {
                        return { ...item, status: 'error' };
                      }
                      return item;
                    });
                    return newStatus;
                  });
                  return;
                }
                const awsXhrResponse: API.awsCompletedResponse = JSON.parse(
                  awsCompletesFileUploadXhr.responseText,
                );
                if (awsXhrResponse && awsXhrResponse.success) {
                  const awsResData = awsXhrResponse.data[0];
                  const paramData = {
                    botFileId: awsResData.id,
                    url: awsResData.link,
                    botFileKey: awsResData.name,
                    openaiFileId: awsResData.openaiFileId,
                    type: 1,
                    fileUId: file.uid,
                  };

                  setUploadedFileList((prevList) => [...prevList, paramData]);

                  setUploadStatus((prevStatus) => {
                    const newStatus = prevStatus.map((item: any) => {
                      if (item.uid === file.uid) {
                        return { ...item, status: 'success', percent: 100 };
                      }
                      return item;
                    });
                    return newStatus;
                  });
                }
              };
              awsCompletesFileUploadXhr.onerror = () => {
                onError(new Error('AWS Completion error'));
                setUploadStatus((prevStatus) => {
                  const newStatus = prevStatus.map((item: any) => {
                    if (item.uid === file.uid) {
                      return { ...item, status: 'error' };
                    }
                    return item;
                  });
                  return newStatus;
                });
              };
              awsCompletesFileUploadXhr.setRequestHeader('Content-Type', 'application/json');
              awsCompletesFileUploadXhr.setRequestHeader('Authorization', `Bearer ${getToken()}`);
              const rasKey = getRasKey();
              if (typeof rasKey === 'string') {
                awsCompletesFileUploadXhr.setRequestHeader('api-pass-key', rasKey);
              }
              awsCompletesFileUploadXhr.send(JSON.stringify(awsCompletesFileUploadFormData));
            }
            onSuccess(response);
          };

          awsXhr.onerror = () => {
            onError(new Error('AWS Upload error'));
            setUploadStatus((prevStatus) => {
              const newStatus = prevStatus.map((item: any) => {
                if (item.uid === file.uid) {
                  return { ...item, status: 'error' };
                }
                return item;
              });
              return newStatus;
            });
          };
          awsXhr.open('PUT', awsUrl, true);
          awsXhr.setRequestHeader('Content-Type', file.type);
          awsXhr.send(file);
        };

        xhr.onerror = () => {
          onError(new Error('Upload error'));
          setUploadStatus((prevStatus) => {
            const newStatus = prevStatus.map((item: any) => {
              if (item.uid === file.uid) {
                return { ...item, status: 'error' };
              }
              return item;
            });
            return newStatus;
          });
        };

        xhr.open('POST', '/api/sapien-storage/v1/file/frontEndUploads', true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.setRequestHeader('Authorization', `Bearer ${getToken()}`);
        const rasKey = getRasKey();
        if (typeof rasKey === 'string') {
          xhr.setRequestHeader('api-pass-key', rasKey);
        }
        xhr.send(JSON.stringify(formData));
      },
    };
  };

  useEffect(() => {
    if (currentUploadFileList.length === uploadedFileList.length) {
      updateFileList(uploadedFileList);
    }
  }, [uploadedFileList]);

  // upload close
  const interruptUpload = (file: any) => {
    const xhr = uploadRequests.get(file.uid);
    if (xhr) {
      xhr.abort();
      setUploadStatus((prevStatus) => {
        const newStatus: any = [...prevStatus];
        const fileIndex = newStatus.findIndex((item: any) => item.uid === file.uid);
        if (fileIndex !== -1) {
          newStatus[fileIndex].status = 'suspend';
          newStatus[fileIndex].percent = 0;
        }

        return newStatus;
      });

      setUploadRequests((prevRequests) => {
        const newRequests = new Map(prevRequests);
        newRequests.delete(file.uid);
        return newRequests;
      });

      setDefaultFileList((prevFileList: any) => {
        const newFileList = prevFileList.map((item: any) => {
          if (item.uid === file.uid) {
            return { ...item, status: 'error' };
          }
          return item;
        });
        return newFileList;
      });

      const newFileList = defaultFileList.map((item: any) => {
        if (item.uid === file.uid) {
          return { ...item, status: 'error' };
        }
        return item;
      });
      updateFileList(newFileList);
    }
  };

  const deleteUpload = (file: any) => {
    const index = uploadStatus.findIndex((item) => item === file);
    if (index > -1) {
      const newUploadStatus = [...uploadStatus];
      newUploadStatus.splice(index, 1);
      setUploadStatus(newUploadStatus);
    }
  };
  // Upload End

onChange 里面setDefaultFileList就是把上传的文件列表放里面,方便之后对比文件上传的数量

setUploadRequests 方法是我用来close 上传用的,用不到请忽略

setUploadStatus 方法是我用来展示上传的状态用的,用不到可以忽略
下面这个代码就是我组装已经上传完的数据,之后用来作对比的

const paramData = {
                    botFileId: awsResData.id,
                    url: awsResData.link,
                    botFileKey: awsResData.name,
                    openaiFileId: awsResData.openaiFileId,
                    type: 1,
                    fileUId: file.uid,
                  };

                  setUploadedFileList((prevList) => [...prevList, paramData]);

比较长度,如果一致,那就走上传的逻辑

  useEffect(() => {
    if (currentUploadFileList.length === uploadedFileList.length) {
      updateFileList(uploadedFileList);
    }
  }, [uploadedFileList]);

七八个前端经手了,到我这里我也不知道该咋样了,反正最后是实现了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字体表绘制的理解

下载字体到项目根目录下&#xff0c;我们通过一些在写预览本地字体的网站&#xff0c;简单看一下 通过图片不难看出阴书与原文的对应关系&#xff0c;接下来通过程序去完成这一过程&#xff0c;通过 fonttools 处理 ttf&#xff0c;然后获取字体和文字对应的 xml 文件 下面简单…

分布式SQL查询引擎之ByConity

ByConity 是字节跳动面向现代数据栈的一款开源数仓系统&#xff0c;应用了大量数据库成熟技术&#xff0c;如列存引擎&#xff0c;MPP 执行&#xff0c;智能查询优化&#xff0c;向量化执行&#xff0c;Codegen&#xff0c;indexing&#xff0c;数据压缩&#xff0c;适合用于 O…

线程池和进程池,输出有区别吗?

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor def fn(name):for i in range(1000):print(name,i)if __name__ __main__:with ThreadPoolExecutor(10) as t:for i in range(100):t.submit(fn,namef"线程{i}")with ProcessPoolExecutor(10…

艾体宝干货 | 如何分析关键网络性能指标?持续接收样品试用申请!

网络性能是企业顺利运营的重要基础&#xff0c;而Allegro流量分析仪作为一款强大的网络性能分析工具&#xff0c;为企业提供了深入了解网络运行状况的途径。在本文中&#xff0c;我们将探讨如何利用Allegro 流量分析仪分析关键网络性能指标&#xff0c;以优化网络性能、提高安全…

【综合案例】使用DevEco Studio编写京东登录界面

效果展示 模块拆分 布局容器 顶部 Logo输入框登录区域底部模块区域 知识点 复选框 Checkbox一段文本多个样式&#xff1a;Text 包裹 SpanRow 或 Column 空白区域填充&#xff1a;Blank线性渐变背景&#xff1a; .linearGradient({angle: 135, // 设置颜色渐变起始角度为顺时针…

BUGKU-WEB-文件包含

解题思路 你说啥我就干啥&#xff1a;点击一下试试你会想到PHP伪协议这方面去嘛&#xff0c;你有这方面的知识储备吗&#xff1f;看到?fileXXX.php&#xff0c;那不就是典型的文件包含吗&#xff1f;这里需要用的一个伪协议php://filter:是一种元封装器&#xff0c; 设计用于…

Python学习计划——7.2数据可视化

数据可视化是数据分析的重要组成部分&#xff0c;通过图表和图形将数据直观地展示出来&#xff0c;帮助我们发现数据中的模式和趋势。Python中常用的数据可视化库有matplotlib和seaborn。以下是对这些库的详细讲解及可运行的Python案例。 1. matplotlib 库 matplotlib 是一个…

RuntimeError: TensorRT currently only builds wheels for x86_64 processors

jetson 板卡似乎不能直接使用pip安装tensorrt&#xff0c;可以通过以下方式进行安装 在官网下载对应的tensorrt包 Log in | NVIDIA Developer 在包里面有python库 pip install 对应python版本的库 安装完成之后在终端 import tensorrt 测试是否安装成功

ubuntu 查找文件find

find -name xxx 查找当前路径下名字为xxx的文件 find . -name xxx 查找当前路径下名字为 train_logs的文件 find . -name train_logs 具体说明 【Ubuntu】find命令_ubuntu find命令-CSDN博客 其中&#xff0c;路径 指定要搜索的目录路径&#xff0c;而 表达式 用于指定匹配条…

单片机外围设备-TFTLCD

stm32f103zet6的fsmc接口实现 8080 时序驱动tftlcd显示&#xff0c;驱动IC是ILI9341。 1、什么是FSMC? FSMC (flexible static memory controller)灵活的静态存储控制器&#xff0c;可以驱动SRAM、 NAND FLASH、 NOR FLASH 和 PSRAM 等存储器。 1、1fsmc框图 1、2fsmc外部设…

18万就能买华为智驾车,你当不了韭菜!

文 | AUTO芯球 作者 | 雷慢 万万没想到啊&#xff0c; 把智能驾驶汽车价格打到最低的&#xff0c; 居然是智驾实力最强的华为&#xff0c; 这你敢信吗 就现在&#xff0c;17.99万就能买华为智驾的车了&#xff0c; 它就是长安和华为合作的首个车型&#xff0c; 深蓝S07…

Python酷库之旅-第三方库Pandas(055)

目录 一、用法精讲 206、pandas.Series.reset_index方法 206-1、语法 206-2、参数 206-3、功能 206-4、返回值 206-5、说明 206-6、用法 206-6-1、数据准备 206-6-2、代码示例 206-6-3、结果输出 207、pandas.Series.sample方法 207-1、语法 207-2、参数 207-3、…

【Python学习手册(第四版)】学习笔记09.1-Python对象类型-元组

个人总结难免疏漏&#xff0c;请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 目录 元组 元组操作 实际应用 元组的特殊语法&#xff1a;逗号和圆括号 转换、方法以及不可变性 index、count及其他方法 有了列表为什么还要元组 元组 元…

可视化目标检测算法推理部署(二)YOLOv8模型图像推理

在先前的RT-DETR中&#xff0c;博主使用ONNX模型文件进行了视频、图像的推理&#xff0c;在本章节&#xff0c;博主打算使用YOLOv8模型进行推理&#xff0c;因此&#xff0c;我们除了需要获取YOLOv8的ONNX模型文件外&#xff0c;还需要进行一些额外的操作&#xff0c;如NMS后处…

PHP在线加密系统源码

历时半年&#xff0c;它再一次迎来更新[飘过] 刚刚发的那个有点问题&#xff0c;重新修了一下 本次更新内容有点多 1. 更新加密算法&#xff08;这应该是最后一次更新加密算法了&#xff0c;以后主要更新都在框架功能上面了&#xff09; 2. 适配php56-php74 3. 取消批量加…

【机器学习西瓜书学习笔记——神经网络】

机器学习西瓜书学习笔记【第四章】 第五章 神经网络5.1神经元模型5.2 感知机与多层网络学习感知机学习率成本/损失函数梯度下降 5.3 BP神经网络&#xff08;误差逆传播&#xff09;5.4 全局最小与局部极小5.5 其他常见神经网络RBF网络RBF 与 BP 最重要的区别 ART网络 第五章 神…

【Linux】进程间通信 —— 管道与 System V 版本通信方式

目录 为什么有进程间通信&#xff1f;进程间通信的目的是什么&#xff1f; 管道 匿名管道 父子进程共享管道 命名管道 共享内存 概念 原理 共享内存和内存映射&#xff08;文件映射&#xff09;的区别 使用 消息队列 概念 使用 信号量 概念 使用 IPCS 命令 S…

【人工智能专栏】Cross Entropy 交叉熵损失解析

Cross Entropy 交叉熵 信息熵 在信息世界中我们所有的信息都可以抽象为“情况”,用二进制 bit 来表达,正因为每个 bit 都有 0 1 两种“情况”,所以 n n n 个 bit 可以编码 2 n 2^n 2

Java----代理

什么是代理&#xff1f; 在Java中&#xff0c;代理是一种用于创建一个或多个服务的中间层&#xff0c;它可以拦截并处理程序对实际服务对象的请求。代理模式是一种设计模式&#xff0c;属于结构型模式&#xff0c;它允许程序员在不修改实际对象代码的情况下&#xff0c;增强或控…

PHP反序列化漏洞从入门到深入8k图文介绍,以及phar伪协议的利用

文章参考&#xff1a;w肝了两天&#xff01;PHP反序列化漏洞从入门到深入8k图文介绍&#xff0c;以及phar伪协议的利用 前言 本文内容主要分为三个部分&#xff1a;原理详解、漏洞练习和防御方法。这是一篇针对PHP反序列化入门者的手把手教学文章&#xff0c;特别适合刚接触PH…