Ant Design Vue Upload 自定义上传 customRequest,这一篇很详细

Upload 常用属性和方法

在这里插入图片描述

示例上传接口

# 接口文档
url `https://www.mocky.io/api/main/upload`
头部
x-token: 'xxx'  
参数
file: File   // 上传的文件
flag: 'xxx'  // 上传的标识
// 文件上传 api 函数简单封装
export const uploadApi = ({ file }) => {
  const formData = new FormData();
  formData.append('file', file);
  // ... 略,formData 其他实现逻辑
  return axios({
    url: '/api/upload',
    method: 'POST',
    data: formData,
    headers: {
      'Content-type': 'multipart/form-data',
    },
  });
};

组件基本使用

<a-upload
    v-model:file-list="fileList"
    name="file"
    :multiple="true"
    action="https://www.mocky.io/api/main/upload"
    :headers="{ x-token: 'xxx' }"
    :data="{ flag: 'xxx' }"
    @change="handleChange"
  >
    <a-button>点击上传</a-button>
</a-upload>

基本使用方式可以满足大部分上传需求,但是也存在局限性,仅限于配合该组件的属性使用。如果是已经封装好了上传的请求函数(包括头部信息和请求中间件等),可在多个地方使用,还使用该方式拼接 data,headers 就有点冗余了。

customRequest 自定义上传

简单使用

使用组件的 customRequest 属性覆盖默认的上传行为,可以自定义自己的上传实现

<a-upload
    v-model:file-list="fileList"
    list-type="picture-card"
    name="file"
    :multiple="true"
    :customRequest="customUpload"
    @change="handleChange"
>
    <upload-outlined></upload-outlined>
</a-upload>

<script>
...
const fileList = ref([]);

// 自定义文件上传公共函数
// e - 上传组件返回的上传实例,里面包括 file,和一些组件方法
// e.file - 上传的文件实例对象
// e.onSuccess(ret, xhr)
// e.onError(err, ret)
const customUpload = (e) => {
  console.log(e);
  // uploadApi 你的二次封装上传接口  
  uploadApi({
      file: e.file
  })
    .then((res) => {
      console.log('上传成功', res.data);
      // 调用实例的成功方法通知组件该文件上传成功
      e.onSuccess(res.data, e);  
    })
    .catch((err) => {
      // 调用实例的失败方法通知组件该文件上传失败
      e.onError(err);
    });
};

</script>


这样的话,实现自定义的上传函数,二次封装上传接口,例如在uploadApi使用 axios 对基本路径、头部信息和请求参数的封装。

在请求成功后调用组件实例成功回调onSuccess(ret,xhr),回传的ret 将会存放在fileList 中的 file.response 中,可运用这点存放所需的数据。

进度条的实现

由于前面 简单使用 的时候我们自定义了上传逻辑,组件未能监听到上传的进度 fileList 中的 file.percent 会一直处于 0 的状态。所以下面我们实现一下请求进度逻辑,补全该进度条。

// 自定义文件上传公共函数
// e.onProgress(event)  event的格式为 {percent:xxx}
const customUpload = (e) => {
  console.log(e);
  // 上传接口  e.file 就是接口所用的 file
  uploadApi({
    file: e.file,
    onUploadProgress: (ev) => {
      // ev - axios 上传进度实例,上传过程触发多次
      // ev.loaded 当前已上传内容的大小,ev.total - 本次上传请求内容总大小
      console.log(ev);
      const percent = (ev.loaded / ev.total) * 100;
      // 计算出上传进度,调用组件进度条方法
      e.onProgress({ percent });
    },
  })
    .then((res) => {
      console.log('上传成功', res.data);
      e.onSuccess(res.data, e);
    })
    .catch((err) => {
      e.onError(err);
    });
};

看上去也就多了个onUploadProgress参数。不过这个参数并非只是 uploadApi 方法的。还需要在请求实例(axios)中配置该上传进度回调参数。

// 文件上传 api
export const uploadApi = ({ file, onUploadProgress }) => {
  const formData = new FormData();

  formData.append('file', file);
  // ... 略,formData 其他实现逻辑

  return axios({
    url: '/api/upload',
    method: 'POST',
    data: formData,
    headers: {
      'Content-type': 'multipart/form-data',
    },
    onUploadProgress, // 上传进度回调函数 onUploadProgress(ev)
  });
};

实现了上传进度逻辑,自定义上传的文件列表 fileList 中的 file.percent 才会正确反应进度情况

配合表单组件使用

以 Vue3 的概念逻辑代码为例

<a-form :model="formInfo">
  <a-form-item label="your name">
    <a-input v-model:value="formInfo.name" />
  </a-form-item>

  <a-form-item label="身份证上传">
    <a-upload
      v-model:file-list="fileList"
      list-type="picture-card"
      name="file"
      :multiple="true"
      :customRequest="customUpload"
      @change="handleChange"
    >
      <upload-outlined></upload-outlined>
    </a-upload>
  </a-form-item>

  <a-form-item :wrapper-col="{ span: 14, offset: 4 }">
    <a-button type="primary" @click="onSubmit">Submit</a-button>
    <a-button style="margin-left: 10px">Cancel</a-button>
  </a-form-item>
</a-form>

<script>
...

const fileList = ref([]);
const formInfo = reactive({
  name: '阿姣🐷',
});

// 获取上传成功的文件 url 数组
const getSuccessFileUrls = (list) => {
  let urls = [];
  list.forEach((item) => {
    // 获取上传成功的文件数据
    if (item.status === 'done' && item.response) {
      urls.push(item.response.url); //改为你想获取的数据格式
    }
  });
  return urls;
};

// 表单提交
const onSubmit = () => {
  const urls = getSuccessFileIds(fileList.value);
  console.log(urls);
  console.log(toRaw(formInfo));
  ...
  submitInfoApi(data)
      .then(res=>{})
      .cathc(err=>{})
};
</script>

获取详情后回显表单

请求信息详情接口成功后,将图片文件等url重新按照 fileList 的格式赋值文件列表。

<script>
const fileList = ref([]);

const fetchDetail = ()=>{
    getInfoDetail(data).then(res=>{
       let imageUrls = res.data.images; // 详情数据 
       imageUrls.forEach(item=>{
           let newItem = {
              uid: 'xxxx1',
              response: {
                id: 'xxxx1',
                origin_name: 'image1.png',
                url: 'http://xxx/image1.png',
              },
              name: 'image1.png',
              status: 'done',
              url: 'http://xxx/image1.png',
           };
           fileList.value.push(newItem); // 赋值文件列表
       });
       ...
    });
}
</script>

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级罗伯特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值