antd上传组件upload踩坑和封装

效果图:

1、公共组件封装:

将antd中的上传组件进行改进:

不同文件格式使用不同上传样式;

增加上传限制:大小,数量,尺寸;

UploadCustom.js

import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { Button, message, Modal, Upload } from 'antd';
import Axios from 'axios';
import bytes from 'bytes';
import dayjs from 'dayjs';
import React, { memo, useEffect, useState } from 'react';
import { getRandomIntInclusive } from '../../utils/utils';

function UploadOSS(props) {
  const {
    onChange,
    value,
    dirPath,
    listType,
    multiple,
    accept,
    limit,
    sizeLimit,
    className,
    width,
    height,
  } = props;
  const [uploadData, setUploadData] = useState({});
  let flag = false;

  // 初始化上传所需参数(从接口获取,过程省略)
  const init = async () => {
    setUploadData({});
  };

  useEffect(() => {
    init();
  }, [dirPath]);

  // 捕捉上传出错的文件
  const handleChange = ({ file, fileList }) => {
    if (file.status === 'error') {
      message.error('上传出错!');
    }
    if (onChange) {
      onChange(fileList.filter((v) => v.status === 'done' || v.status === 'uploading'));
    }
  };

  // 移除文件
  const onRemove = (file) => {
    const files = value.filter((v) => v.url !== file.url);
    if (onChange) {
      onChange(files);
    }
  };

  // 上传之前转换对象
  const transformFile = (file) => {
    const suffix = file.name.slice(file.name.lastIndexOf('.'));
    const filename = `${getRandomIntInclusive(1000, 9999)}-${dayjs().format(
      'YYYY-MM-DD',
    )}${Date.now()}${suffix}`;
    file.url = `${dirPath}${filename}`;
    return file;
  };

  // 上传所需额外参数
  const getExtraData = (file) => {
    return {
      key: file.url,
      success_action_status: 200,
      policy: uploadData.policy,
      Signature: uploadData.signature,
    };
  };

  // 图片尺寸比例限制
  const checkSize = (file) => {
    return new Promise((resolve, reject) => {
      const url = window.URL || window.webkitURL;
      const img = new Image();
      img.onload = () => {
        const valid =
          img.width >= width && img.height >= height && img.width / img.height === width / height;
        valid ? resolve() : reject();
      };
      img.src = url.createObjectURL(file);
    }).then(
      () => {
        return true;
      },
      () => {
        if (flag) {
          Modal.error({
            title: `图片尺寸不符合要求,请修改后重新上传!`,
          });
          flag = false;
        }
        return Promise.reject();
      },
    );
  };

  // 图片大小限制
  const checkLimit = (file) => {
    return new Promise((resolve, reject) => {
      file.size <= sizeLimit ? resolve() : reject();
    }).then(
      () => {
        return true;
      },
      () => {
        if (flag) {
          Modal.error({
            title: `超过大小限制${bytes(sizeLimit)},请重新选择!`,
          });
          flag = false;
        }
        return Promise.reject();
      },
    );
  };

  // 数量限制
  const checkLen = (fileList) => {
    return new Promise((resolve, reject) => {
      const isLen = value.length + fileList.length;
      isLen <= limit ? resolve() : reject();
    }).then(
      () => {
        return true;
      },
      () => {
        if (flag) {
          Modal.error({
            title: `超过最大上传数量${limit}张,请重新选择!`,
          });
          flag = false;
        }
        return Promise.reject();
      },
    );
  };

  // 判断所有条件满足才能上传
  const beforeUpload = async (file, fileList) => {
    flag = true;
    const isLen = limit ? await checkLen(fileList) : true;
    const isSizeLimit = sizeLimit ? await checkLimit(file) : true;
    const isSize = width ? await checkSize(file) : true;
    const expire = uploadData.expire * 1000;
    if (expire < Date.now()) {
      await init();
    }
    return isLen && isSizeLimit && isSize;
  };

  // 图片预览处理
  const handlePreview = async (file) => {
    let src = file.url;
    if (!src || src.indexOf('http') === -1) {
      src = await new Promise((resolve) => {
        const reader = new FileReader();
        reader.readAsDataURL(file.originFileObj);
        reader.onload = () => resolve(reader.result);
      });
    }
    const image = new Image();
    image.src = src;
    const imgWindow = window.open(src);
    imgWindow.document.write(image.outerHTML);
  };

  const uploadProps = {
    name: 'file',
    fileList: value,
    action: uploadData.host,
    onChange: handleChange,
    data: getExtraData,
    onPreview: handlePreview,
    onRemove,
    transformFile,
    beforeUpload,
    listType,
    multiple,
    accept,
    className,
  };

  // 文件和图片使用不同的样式
  const Con = () =>
    listType ? (
      <div>
        <PlusOutlined />
        <div className="ant-upload-text">上传</div>
      </div>
    ) : (
      <Button>
        <UploadOutlined /> 上传
      </Button>
    );

  return <Upload {...uploadProps}>{value && value.length < limit && Con()}</Upload>;
}

export default memo(UploadCustom);

使用组件:

index.js

import UploadCustom from '';


return (
  <>
    <UploadCustom
        dirPath="files/"
        limit={1}
        sizeLimit={bytes('2GB')}
        accept=".exe,.msi,.rar,.zip,.7z"
    ></UploadCustom>

    <UploadCustom
        dirPath="appstore/adp/logo/"
        listType="picture-card"
        accept="image/*"
        limit={1}
        sizeLimit={bytes('5MB')}
        className="upload-list-inline"
        width={256}
        height={256}
     ></UploadCustom>
  </>
)

 

在Vue项目中封装Ant Design Vue (简称AV) 的 Upload 组件可以帮助你更方便地管理文件上传的功能,并保持代码整洁。以下是步骤概述: 1. **安装依赖**: 首先需要安装 `@antv/vue-upload` `axios` 或者 `fetch` 等用于发送请求的库。可以使用 npm 或 yarn 安装: ``` npm install @antv/vue-upload axios ``` 2. **创建封装Upload组件**: 创建一个名为 `Upload.vue` 的文件,例如: ```html <template> <a-upload :action="uploadUrl" :on-success="handleSuccess" :before-upload="beforeUpload"> <a-icon type="upload" slot="trigger"></a-icon> <p slot="text">点击上传</p> <a-button type="primary" slot="dragger" @click="submitFile">选择文件</a-button> </a-upload> </template> <script> export default { components: { ... }, data() { return { uploadUrl: '', file: {}, submitting: false, }; }, methods: { beforeUpload(file) { // 可以在这里做预处理,比如检查文件类型、大小等 if (/* your conditions */) { return true; } return false; }, handleSubmit() { this.submitting = true; }, handleSuccess(res) { this.file = {}; this.submitting = false; console.log('上传成功', res); }, }, }; </script> ``` 3. **在父组件中使用**: 在需要上传功能的地方引入并使用这个封装好的 Upload 组件,传入相应的 URL 其他配置选项。 4. **额外配置**: - 如果需要上传文件前的验证,可以在 `beforeUpload` 方法中添加自定义逻辑。 - 可以设置上传进度条、断点续传等功能,查看 Ant Design Vue Upload 文档获取更多信息。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值