介绍
江流儿是21届毕业生,是个热爱前端开发的好少年,喜欢收藏唯美壁纸与技术交流,此篇文章是江流的首秀,同时也作为笔记,不足之处还希望大佬指点出来,先放壁纸👇👇👇
(图片来源网络侵权请留言)
这次主要分享的内容是antd的upload组件,我想如果公司业务没有涉及到这个上传业务的话我也不会去阅读upload的源码,为什么阅读这个组件的源码呢?有办法么?业务需要自定义,那为什么做这个分享呢?江流儿这几天一直收集相关的资料,发现关于自定义上传的资料,能让我看懂的实在是少的可怜,有办法嘛?
下面进入正题👇👇👇
customRequest提供的API
先上API
onError 参数
err: 请求错误信息response: 请求响应,不支持 iframeUploadfile: 上传文件
onSuccess 参数
result: 响应体file: 上传文件xhr: xhr 标头,仅适用于支持 AJAX 上传的现代浏览器。从 2.4.0 开始
自定义请求
允许通过覆盖 AjaxUploader 中的默认行为进行高级自定义。提供您自己的 XMLHttpRequest 调用以与自定义后端进程交互或通过 aws-sdk-js 包与 AWS S3 服务交互。
customRequest 回调传递一个对象:
onProgress: (event: { percent: number }): voidonError: (event: Error, body?: Object): voidonSuccess: (body: Object): voiddata: Objectfilename: Stringfile: FilewithCredentials: Booleanaction: Stringheaders: Object以上是源码提供的材料👆👆👆
这几个操作方法有几个值得注意的:
- onProgress方法:获取进度的方法,但是这个进度每次调用只返回一个百分比,配合antd的Progress组件的话需要自己转化一下
- file:这个是你要上传的文件,但是相比较antd已经封装好的会提供一个fileList(受控的),而file是一个对象,所以想要通过遍历的方式创建一个自定义的下载列表,需要包装
- onSuccess:上传成功的回调,在这里可以执行自己上传后想要处理的逻辑,下面代码是结合antd的全局提醒,当然你可以写更复杂的逻辑
customRequest例子
这里废话不多说,直接代码+注释
/* eslint-disable no-self-compare */
import React, { useState } from 'react'
import { Upload, Button, List,message } from 'antd'
import axios from 'axios'
const Myupload = () => {
const [fileList, setFileList] = useState([])
const uploadconfig = {
action: '',//必填的url
multiple: false,//是否允许一次上传多个文件
headers: {
Authorization: '$prefix $token',//请求头
},
onStart(file) {//这是这个函数开始执行时的打印传入的文件
console.log('onStart', file, file.status);
},
onSuccess(res, file) {//上传成功的回调函数
console.log('onSuccess', res, file.name);
message.success(`${file.name}上传成功`)
},
onError(err) {//上传出错的回调函数
console.log('onError', err);
message.error(`上传失败`)
},
onProgress({ percent }, file) {//axios提供的获取进度(注意:此处有坑,江流儿尚未解决)
//再次回调函数中可以获取到进度,但是想要更新进度条就要在此函数中赋值,就会出现下面描述的bug
console.log('onProgress', `${percent}%`, file.name);
setFileList([{name:file.name,percent:parseInt(percent),uid:file.uid}])
//在这里可以看到是给fileList赋值了的,但是这里只允许上传一个文件,如果上传多个,就会出现bug
//bug:如果上传多个,会出现自定义下载列表的闪烁问题
//(这个问题江流儿也没有解决,希望有大佬指点迷津)
},
onRemove:() => delPackage,//删除的回调
customRequest({
action,
file,
filename,
headers,
onError,
onProgress,
onSuccess,
withCredentials,
}) {
// EXAMPLE: post form-data with 'axios'
// eslint-disable-next-line no-undef
const formData = new FormData();
formData.append(filename, file);
var CancelToken = axios.CancelToken;//拿到中断请求的方法
var source = CancelToken.source();//同上
axios
.post(action, formData, {
withCredentials,
headers,
onUploadProgress: ({ total, loaded }) => {
onProgress({ percent: Math.round((loaded / total) * 100).toFixed(2) }, file);
},
})
.then(({ data: response }) => {
onSuccess(response, file);
})
.catch(onError);
return {
abort() {
console.log('终止函数');//此处的函数仅仅是一个函数,而当你创建axios实例时,你会发现根本没有abort方法(应该是我的问题吧)
//想要定义终止函数需要以下代码👇
source.cancel()
//为什么不用老的方法呢?是因为axios也变了,有办法么?没有办法。谁让我迭代了个老项目呢(入世太浅,努力学习)
},
};
},
};
const delPackage = (file,index) => {
//...你的自定义删除逻辑
}
const { Item } = List;
return <div>
<Upload {...uploadconfig} showUploadList={false}>
<Button type='primary'>点击上传</Button>
</Upload>
<List
itemLayout='vertical'
>
{
fileList.map((item,index) => {
return (<Item key={index}>
<div>{item.name}</div>
<div>进度:{item.percent}</div>
<div><Button onClick={() => { delPackage(item,index) }} type='primary'>删除</Button></div>
</Item>)
})
}
</List>
</div>
}
export default Myupload
上述代码可以完成的业务仅仅支撑本地上传单个文件,为什么没有讲上传多个文件呢?因为我也不会,等我研究出来在更,如果有大佬能看出我的忧伤~^_^,请帮帮孩子,如果有遇到此类问题的朋友,欢迎留言交流。
江流儿寄语(不是很重要,选择性阅读):江流儿觉得,如果你能把文章看到这里了,就给江流儿一个赞吧,江流儿也努力成为一个高质量文章输出者,替更多的人解决问题,一路自学过来,就好像很火的一句话,“自己淋过雨,所以想为他人撑把伞吧。”欢迎想学前端,但是迷茫的小伙伴咨询哦😁
感谢阅读哦