需求

由于使用antd 上传图片,在某些情况下,例如token 失效,导致上传图片错误,但是antd 组件始终会走onChange 事件
导致上传路径为空情况

解决办法

使用自定义上传

 // 自定义上传图片const customRequest = params => {const { file, onSuccess, onError } = params;const formData = new FormData();formData.append('upload_file', file);Resource.handleUploadPicture(formData).then(ret => {if (ret?.XCmdrCode === 0) {if (typeof setPictureList === 'function') {const temFile = {...ret?.XCmdrResult,};onSuccess(ret); // 上传成功的图片会显示绿色的对勾let newFiles = [...fileListRef.current, temFile];if (!multiple) {// 只保留最后一个文件newFiles = newFiles.slice(-1);}setPictureList(_, newFiles);}} else {message.error(`${ret?.XCmdrMessage}`);}}).catch(ret => {onError();});};// 图片属性配置const pictureProps = {action: `https://admin-api.zhgcloud.com/attachments?token=${token}`,name: 'upload_file',// action: `https://admin-api.zhgcloud.com/images?token=${token}`,// name: 'machine_image',listType: 'picture-card',fileList,multiple,...res,beforeUpload: onBeforeUpload || defaultBeforeUpload,onChange: ({ file, fileList, event }) => {// let newFiles = [...fileList];// if (!multiple) {//     // 只保留最后一个文件//     newFiles = newFiles.slice(-1);// }// if (typeof setPictureList === 'function') {//     setPictureList(file, newFiles);// }},customRequest,onRemove: file => {const freshFiles = fileList?.filter(ele => ele.uid !== file.uid);if (typeof onRemove === 'function') {onRemove(file, freshFiles);}},onPreview: async file => {if (!file.url && !file.preview) {file.preview = await getBase64(file.originFileObj);}setUrl(file?.url || file?.response?.XCmdrResult?.url || file.previe);},onDownload: onDownload || defaultOnDownload,};

完整组件逻辑

import React, { useEffect, useState, useRef, forwardRef, useImperativeHandle, onBeforeUpload } from 'react';
import { PlusOutlined } from '@ant-design/icons';
import { Upload, Modal, message } from 'antd';
import { saveAs } from 'file-saver';
import { useMount, useUnmount } from 'ahooks';
import FileViewer from '@/components/FileViewer';
import useToken from '@/hooks/useToken';
import Resource from '@/services/Resource';const MAX_FILE_SIZE = 8;
const UNIT = 1024 * 1024;
function getBase64(file) {return new Promise((resolve, reject) => {const reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => resolve(reader.result);reader.onerror = error => reject(error);});
}
const createFileObject = file => {const fileObject = {lastModified: file.lastModified,lastModifiedDate: file.lastModifiedDate,name: file.name,size: file.size,type: file.type,uid: file.uid,};return fileObject;
};
const defaultOnDownload = file => {// if (file?.url || file?.response?.XCmdrResult?.url) {//     window.open(file.url, '_blank');// }const url = file?.url || file?.response?.XCmdrResult?.url;saveAs(url, `${file?.name || file?.url || ''}`);
};
const defaultBeforeUpload = file => {const fileType = ['jpg', 'jpeg', 'png'];// 文件显示return new Promise((resolve, reject) => {const curType = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();if (!fileType.includes(curType)) {Modal.warning({maskClosable: true,title: '图片格式须为jpg、jpeg、png!',});// reject(file);return Upload.LIST_IGNORE;} else if (file.size > MAX_FILE_SIZE * UNIT) {Modal.warning({maskClosable: true,title: `单个图片大小不能超过${MAX_FILE_SIZE}M!`,});return Upload.LIST_IGNORE;} else {resolve(file);}});
};
const UploadPicture = ({refChildPicture,limit = 3,action,onRemove,setPictureList = () => {},onDownload,pictures = [],isPaste = false,multiple = true,outlinedName = '上传图片',...res
}) => {const [fileList, setFileList] = useState([]);const [url, setUrl] = useState('');const token = useToken();const fileListRef = useRef([]);useEffect(() => {fileListRef.current = [...pictures];setFileList([...pictures]);}, [pictures]);const saveFiles = (file, ret) => {//             // 图片转换成base64编码作为缩略图const reader = new FileReader();// 监听图片转换完成reader.addEventListener('load',() => {// ...接入antd upload 的 filelist 中const temFile = {...file,response: ret,originFileObj: createFileObject(file),id: new Date().getTime(),status: 'done',name: ret?.XCmdrResult?.path || file.name,url: ret?.XCmdrResult?.url,thumbUrl: reader.result,};if (typeof setPictureList === 'function') {let newFiles = [...fileListRef.current, temFile];if (!multiple) {// 只保留最后一个文件newFiles = newFiles.slice(-1);}setPictureList(_, newFiles);}},false,);reader.readAsDataURL(file);};// 自定义上传图片const customRequest = params => {const { file, onSuccess, onError } = params;const formData = new FormData();formData.append('upload_file', file);Resource.handleUploadPicture(formData).then(ret => {if (ret?.XCmdrCode === 0) {onSuccess();saveFiles(file, ret);} else {message.error(`${ret?.XCmdrMessage}`);}}).catch(ret => {onError();});};// 图片属性配置const pictureProps = {action: `https://admin-api.zhgcloud.com/attachments?token=${token}`,name: 'upload_file',// action: `https://admin-api.zhgcloud.com/images?token=${token}`,// name: 'machine_image',listType: 'picture-card',fileList,multiple,...res,beforeUpload: onBeforeUpload || defaultBeforeUpload,onChange: ({ file, fileList, event }) => {// let newFiles = [...fileList];// if (!multiple) {//     // 只保留最后一个文件//     newFiles = newFiles.slice(-1);// }// if (typeof setPictureList === 'function') {//     setPictureList(file, newFiles);// }},customRequest,onRemove: file => {const freshFiles = fileList?.filter(ele => ele.uid !== file.uid);if (typeof onRemove === 'function') {onRemove(file, freshFiles);}},onPreview: async file => {if (!file.url && !file.preview) {file.preview = await getBase64(file.originFileObj);}setUrl(file?.url || file?.response?.XCmdrResult?.url || file.previe);},onDownload: onDownload || defaultOnDownload,};useImperativeHandle(refChildPicture, () => {// return返回的值就可以被父组件获取到return {getFileData() {return {fileList,};},};});useMount(() => {if (!isPaste) {return;}const haoroomsbox = document.getElementById('ant-upload-picture-area-id');haoroomsbox.addEventListener('paste', event => {const data = event.clipboardData || window.clipboardData;const items = data.items;let tempFile = null; // 存储文件数据if (items && items.length) {// 检索剪切板itemsfor (let i = 0; i < items.length; i++) {if (items[i].type.indexOf('image') !== -1) {tempFile = items[i].getAsFile();break;}}}window.willUploadPictureList = tempFile;event.preventDefault();submitUpload(tempFile);});});const submitUpload = file => {if (!file) {return;}if (fileListRef.current && fileListRef.current.length >= limit) {message.error(`上传最大限制数量为${limit}`);return;}const formData = new FormData();formData.append('upload_file', file);Resource.handleUploadPicture(formData).then(ret => {if (ret?.XCmdrCode === 0) {saveFiles(file, ret);} else {message.error(`${ret?.XCmdrMessage}`);}}).catch(ret => {message.error('上传失败');});};useUnmount(() => {const haoroomsbox = document.getElementById('ant-upload-picture-area-id');if (haoroomsbox) {// haoroomsbox.removeEventListener('paste', () => {});}});return (<div ref={refChildPicture} id="ant-upload-picture-area-id"><Upload {...pictureProps}>{fileList && fileList.length >= limit ? null : (<div><PlusOutlined /><div>{outlinedName}</div></div>)}</Upload><FileViewer url={url} onCancel={() => setUrl('')} /></div>);
};export default forwardRef(UploadPicture);

antd Upload 自定义上传相关推荐

  1. React Antd Upload自定义上传customRequest

    单独的上传图片接口要传参,action方式不太适合,需要使用自定义上传customRequest覆盖 公司代码不可弄,就发一个可用的demo例子 import React, { useState } ...

  2. antd Upload组件上传状态一直处于uploading

    antd Upload组件上传状态一直处于uploading 对于受控模式,需要在 onChange 中始终 setState fileList,保证所有状态同步到 Upload 内 import { ...

  3. 使用ngZorro中Upload自定义上传时XMLHttpRequest问题解决方法

    使用ngZorro中Upload自定义上传时XMLHttpRequest问题解决方法 使用angular框架写前端的用户一般都比较喜欢用ngZorro,本人最近在使用ngZorro中的Upload自定 ...

  4. Ant Design Upload 自定义上传 customRequest

    本文章重点描述上传组件 Upload 的 customRequest 自定义文件上传逻辑的实现 目录 Upload 常用属性和方法 默认上传 customRequest 自定义上传 Upload 自定 ...

  5. Antd Upload 文件上传,自定义上传错误信息

    项目需求 使用antd Upload 组件 项目上要求前端对上传不符合标准的图片展示具体的错误信息 不设置action,即返回信息无response ,先在前端上传后调用接口保存 效果截图 主要是根据 ...

  6. antd Upload 文件上传

    1.antd官网Upload组件: https://ant.design/components/upload-cn/ 2.下图是最近开发的上传文档的效果: 3.文件上传的实现: (1)方法一:antd ...

  7. antd upload手动上传_Flask上传文件

    Flask上传文件 上传文件包括很多,比如用户头像,文章图片,文件分享等等,它也涉及到很多内容:上传文件,过滤文件类型,限制大小,文件名的编辑,拖拽上传,进度条,文件命名,文件目录的管理等等. 文件上 ...

  8. antd upload手动上传_基于MVVCTP5的文件上传

    现如今在市面上常见的web开发理念一般是两种,一种是MVC格式的,比较传统,而项目较大的开发,一般由团队完成,而MVC格式就显得有些不够合理 .于是 ,在这种情况下诞生了另外一种开发理念,我们叫MVV ...

  9. antd Upload手动上传(react)

    情况介绍 在antd官方提供的upload组件案例中,都使用了action属性直接上传,唯一手动上传的一个例子(如下图)也不够好用,可能不能满足项目的需求,所以我们需要对其进行一些修改,并加入一些别的 ...

最新文章

  1. mysql半主从_转mysql半主从同步
  2. 别把个人信息“玩”丢了
  3. MySQL的并发控制与加锁分析
  4. opengl 反走样 混合 多重采样 blend multisample
  5. python中函数的参数:必传参数(位置参数)、默认值参数、参数组传参、关键字传参...
  6. Linux知识点记录
  7. 图形基础 GPU架构(5)并行计算
  8. feedburner怎么用_FeedBurner PRO 現在免費使用
  9. 【转】NB的specify
  10. java课时,java学习笔记_课时一
  11. java传文件到kafka_Java将CSV的数据发送到kafka的示例
  12. 什么是垃圾回收(转)
  13. 直方图规定化计算过程
  14. C++之binary_search二分查找算法
  15. 分数阶微积分学薛定宇电子版_分数阶微积分学与分数阶控制
  16. JAVA 小易爱回文
  17. edu教育邮箱免费申请注册Google drive无限网盘和微软OneDrive经验分享
  18. 【mmdeploy】mmseg转ONNX/TensorRT,附推理代码
  19. 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.2/gradle-3
  20. mysql多字段联合搜索和concat带来的问题

热门文章

  1. Hibernate_day01
  2. 【软件推荐】压缩软件——7-Zip
  3. 简述C#中IO的应用
  4. 2020第十七届华为杯数模C题——P300脑电信号数据预处理算法
  5. 新浪微博草根大号困局:新鲜感丧失 商业化过度
  6. 【转】高清混合矩阵应用于佛山市政府大礼堂会议系统解决方案
  7. AcWing1293. 夏洛克和他的女朋友
  8. 中国人保为山东三同新材料承保产品责任险,为消费者保驾护航
  9. 百公里时速不掉线 芯讯通为商用车驾驶安全保驾护航
  10. 2019年最新版 省市区json数据 跟小程序省市区的数据同步