当前位置: 首页 > news >正文

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

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

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

// Uploadinterface 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 filesconst [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 closeconst 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.lryc.cn/news/411017.html

相关文章:

  • ALB快速实现IPv4服务的负载均衡
  • 【LLM】-12-部署Langchain-Chatchat-0.3.x版本
  • 优化网络接收缓存减少数据丢包
  • 数据透视——判别分析
  • 书生大模型学习笔记 - 连接云端开发机
  • Python操作符的重载
  • redis面试(三)Hash数据结构
  • Java基础语法
  • Qt | QChart+QChartView+QLineSeries(折线图)+QBarSeries(柱状图)实战
  • 公布一批脸书爬虫(facebook)IP地址,真实采集数据
  • Package.Json 参数配置理解用途
  • k3:增加触发器,当外协单和报料单新增时,更新生产任务单的“说明”栏
  • 神奇海洋养鱼小程序游戏广告联盟流量主休闲小游戏源码
  • 分享几个适合普通人的AI副业变现思路
  • 如何使用CANoe自带的TCP/IP Stack验证TCP的零窗口探测机制
  • 二进制搭建 Kubernetes v1.20(中)
  • Scrapy 爬取旅游景点相关数据(七):利用指纹实现“不重复爬取”
  • java的对象向上转型
  • Navicat Premium 16破解
  • 【C/C++】C语言到C++的入门知识点(主要适用于C语言精通到Qt的C++开发入门)
  • docker 建木 发版 (详细教程)
  • 什么样的人适合学习网络安全?
  • 大厂linux面试题攻略四之Linux网络服务(二)
  • MySQL和PostgreSQL group by后 Concatenate 拼接所有的字符串
  • Python爬虫技术 第24节 数据清洗和预处理(二)
  • conda常用命令整理
  • JDK8新特性之Lambda表达式快速入门
  • QEMU源码全解析 —— CPU虚拟化(14)
  • libsoup的简单使用
  • electron项目搭建