目录
- 本地上传方法【input type="file"】:
- upload组件【antd】
- 默认接口上传:
- 自定义接口上传:【取消默认上传接口】
- antd的upload组件beforeUpload还有个比较坑的地方
- upload结合裁剪
- 1、antd官方裁剪组件:![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b90d70cf3bc94cc69b7a9dd67df3a90c.png)
- 2、antd裁剪图片二次开发
- 结合form表单使用:
本地上传方法【input type=“file”】:
-
js操作本地文件,通过input type="file"选择本地文件
const fileInput = document.createElement('input'); fileInput.type = 'file'; // js创建file类型input fileInput.click(); // 触发 fileInput?.addEventListener('change', (event) => {const file = event.target?.files[0]; // target返回事件的目标节点,现返回的是input节点本身const reader = new FileReader(); // FileReader 只能访问用户明确选择的文件内容reader.readAsDataURL(file); // readAsDataURL:开始读取指定的 Blob 中的内容。一旦完成,result 属性中将包含一个表示文件数据的 data: URLreader.addEventListener('load', () => {console.log(reader.result);}); });// 用户触发行为点击上传文件 <input type="file" id="file-input"> const fileInput = document.getElementById('file-input'); // 后续同上上传代码
上传的文件想要不同格式时,可以使用FileReader不同的实例方法获取:
-
readAsArrayBuffer() - 标识文件数据的ArrayBuffer对象
-
readAsBinaryString() - 表示文件中原始二进制数据的字符串
-
readAsDataURL() - 表示文件数据的data:URL
-
readAsText() - 表示所读取的文件内容的字符串,可以制定可选的编码名称
-
upload组件【antd】
默认接口上传:
- 使用action属性拼接完整的请求接口地址,eg:action={baseURL + ‘/v1/object/uploadicon’}
- 使用默认上传时注意,需要将token携带到请求头属性中
自定义接口上传:【取消默认上传接口】
-
首先取消默认上传时的接口,在beforeUpload方法return false,来阻止默认上传。即【Upload上传有个action的坑,就是你选择文件之后自动调用地址然后就会执行上传接口,如果不取消会一直有一个失败请求,但不影响主体流程】
-
上传前文件格式校验
-
在上传文件校验或onchange方法中获取上传的文件,进行自定义接口请求传递
const props: UploadProps = {name: 'file',multiple: false,showUploadList: false,async beforeUpload(file) {setImgLoading(true)const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg' || file.type === 'image/webp';const isLt2M = file.size / 1024 / 1024 < 2;const isSize = await new Promise<boolean>((resolve) => {const _URL = window.URL || window.webkitURL;const img = new Image();img.onload = () => {const valid = img.width / img.height === 1;resolve(valid);};img.src = _URL.createObjectURL(file);});if (!isJpgOrPng) {message.error('请上传png、jpeg、jpg、webp格式图片');} else if (!isLt2M) {message.error('上传图片大小不超过2M');} else if (!isSize) {message.error('上传图片比例建议1:1');}if (!isJpgOrPng || !isLt2M || !isSize) {return Upload.LIST_IGNORE;}return false; // 因为自定义接口请求,没有设置action值,所以关闭默认上传事件},onChange(file){const files = new FormData();files.append('file', file.file);// 将files上传给后端接口处理}};
antd的upload组件beforeUpload还有个比较坑的地方
beforeUpload校验不通过return false
的话,onchange中还是会接收到file上传文件信息
解决方法:在beforeUpload校验不通过时return Upload.LIST_IGNORE
阻止文件上传,此时onChange就接收不到不合校验规则的file了
upload结合裁剪
1、antd官方裁剪组件:
裁剪组件是配合 antd-img-crop 实现上传前裁切图片,可以进行属性动态配置
上传前裁剪图片官方使用:
import React, { useState } from 'react';
import { Upload } from 'antd';
import type { GetProp, UploadFile, UploadProps } from 'antd';
import ImgCrop from 'antd-img-crop';type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];const App: React.FC = () => {const [fileList, setFileList] = useState<UploadFile[]>([{uid: '-1',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',},]);const onChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {setFileList(newFileList);};const onPreview = async (file: UploadFile) => {let src = file.url as string;if (!src) {src = await new Promise((resolve) => {const reader = new FileReader();reader.readAsDataURL(file.originFileObj as FileType);reader.onload = () => resolve(reader.result as string);});}const image = new Image();image.src = src;const imgWindow = window.open(src);imgWindow?.document.write(image.outerHTML);};return (<ImgCrop rotationSlider><Uploadaction="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"listType="picture-card"fileList={fileList}onChange={onChange}onPreview={onPreview}>{fileList.length < 5 && '+ Upload'}</Upload></ImgCrop>);
};export default App;
2、antd裁剪图片二次开发
antd官方提供的裁剪可以设置裁剪的比例、形状,放大缩小、旋转按钮显隐等,但一般实际开发时需求与官方例子会略有差异,需要进行裁剪组件源码理解以及二次开发
开发需求要求(重新上传、任务对比框、重新打开裁剪框等):
将antd封装的官方裁剪组件代码拉取到项目中进行再次开发
组件源码目录
具体的二次开发步骤后续更新 ~
结合form表单使用:
上传图片结合form表单使用时,页面的图片字段检测不到Upload上传图片获取的url数据变化导致图片更新问题,如何实现检测数据变化
- 使用
onValuesChange
方法 或 使用Form.useWatch方法 - 还有一个笨方法是,React设置一个setStatus实时变量 和 form对应图片字段进行数值更新,使用实时变量进行页面的渲染
有不对的地方请大佬们指正 ^^