antd封装upload组件

// file.ts类型文件
import { message } from "antd";
import { request } from "ice";

interface DownIdType {
  fileId: string; // 文件id,不能用数字,数字过大会识别不了
  url: string; // 接口地址,有默认
  method?: string; //请求方法
  isDownLoad?: boolean; // 是否下载,如果有多个,则下载多个
}

// 根据id获取文件地址
export const getUrlById = async (options: DownIdType) => {
  const { fileId, url, method, isDownLoad } = options;
  const res = await request({
    url: url,
    method: method || "get",
  });
  if (res?.resp_code === 200) {
    if (isDownLoad) {
      (res.datas || []).forEach((item) => {
        downloadByUrl({
          fileUrl: item.fileUrl,
          fileName: item.fileName,
        });
      });
    }
  }
};
interface DownUrlType {
  fileUrl: string;
  fileName?: string;
}
// 下载
export const downloadByUrl = ({ fileName, fileUrl }: DownUrlType) => {
  const { origin } = window.location;
  if (/^https.+/g.test(origin) && /^http:/g.test(fileUrl)) {
    // 当https调用http时,通过接口调用会失败,所以改成直接打开
    window.open(fileUrl);
    return;
  }
  const xhr = new XMLHttpRequest();
  xhr.open("GET", fileUrl, true);
  xhr.responseType = "blob";
  xhr.onload = function () {
    if (xhr.status === 200) {
      const blob = xhr.response;
      const link = document.createElement("a");
      link.href = window.URL.createObjectURL(blob);
      link.download = fileName || new Date().toLocaleString();
      link.click();
    }
  };
  xhr.send();
};

// 下载Excel
export const downloadExcel = async (fileUrl, fileName) => {
  request({
    url: fileUrl,
    method: "get",
    responseType: "blob",
  }).then((res) => {
    const url = window.URL.createObjectURL(new Blob([res]));
    const link = document.createElement("a");
    link.style.display = "none";
    link.href = url;
    link.setAttribute("download", fileName);
    document.body.appendChild(link);
    link.click();
    link.remove();
  });
};
// 下载文件流

interface DownFileType {
  url: string;
  method?: string;
  fileName?: string;
  params?: Record<string, any>;
  data?: Record<string, any>;
}
export const downloadFile = async ({
  url,
  method,
  fileName,
  params = {},
  data = {},
}: DownFileType) => {
  const res = await request({
    url: url,
    method: method || "get",
    responseType: "blob",
    withFullResponse: true, // 用于取文件名
    params,
    data,
  });
  const resData = res.data;
  if (resData?.type === "application/json") {
    // 下载失败
    try {
      const reader = new FileReader();
      reader.readAsText(resData, "utf-8");
      reader.onload = function () {
        if (typeof reader.result === "string") {
          const result = JSON.parse(reader.result);
          message.error(result.resp_msg || "下载失败");
        }
      };
    } catch (err) {
      message.error("下载失败");
    }
    return false;
  }

//index.tsx
import { useState } from "react";
import { request } from "ice";
import { Upload, message, Modal, Spin } from "antd";
import { downloadByUrl } from "./file";
import env from "@/utils/env";

const BYTE = 1024;
const ACCEPT = {
  zip: "application/zip,application/x-zip,application/x-zip-compressed",
  pdf: "application/pdf",
  excel:
    "application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  image: "image/jpeg,image/bmp,image/png,image/gif",
  word: "application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  ppt: "application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation",
};
const getAccepts = (accept) =>
  (Array.isArray(accept) ? accept : [accept]).map((ac) => ACCEPT[ac]).join(",");
const beforeCheck = (config, file) => {
  const { accept, maxSize = Number.MAX_VALUE } = config || {};
  const { size, type } = file;
  if (Math.pow(BYTE, 2) * maxSize < size) {
    const maxText = maxSize < 1 ? `${maxSize * 1000}K` : `${maxSize}M`;
    message.error(`文件不能超过${maxText}`);
    return false;
  }
  if (accept !== "excel" && type.indexOf(accept)) {
    message.warning("当前上传文件类型不是图片,无法上传!");
    return false;
  }
};

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);
  });
}
export interface FileType {
  uid: string;
  name: string;
  url: string;
  id: string;
  numberId: string;
}

interface PropsType {
  [x: string]: any;
  fileList: FileType[];
}
const UploadComponent = (props: PropsType) => {
  const { children, config, fileList } = props;
  const {
    accept = "*",
    disabled,
    showUploadList,
    data = {},
    maxCount = 10,
  } = config;
  const attrs = {};
  const [previewVisible, setPreviewVisible] = useState(false);
  const [previewImage, setPreviewImage] = useState("");
  const [previewTitle, setPreviewTitle] = useState("");
  const [loading, setLoading] = useState(false);
const handlePreview = async (file) => {
    let path = file.url || file.preview;
    if (/\.(jpeg|jpg|bmp|png|gif)$/g.test(path)) {
      if (!path) {
        path = await getBase64(file.originFileObj);
      }
      setPreviewImage(path);
      setPreviewVisible(true);
      setPreviewTitle(file.name || path.substring(path.lastIndexOf("/") + 1));
    } else {
      downloadByUrl({ fileName: file.name, fileUrl: path });
    }
  };

  const handleRemove = async (file) => {
    const reqData = {};
    setLoading(true);
    const res = await request({
      url: `/v1/file/delete?id=${file.id}`,
      baseURL: env.apiService.baseUrl,
      method: "post",
    });
    setLoading(false);
    if (res?.resp_code === 200) {
      const delData = fileList.filter((item) => item.uid !== file.uid);
      message.success("删除成功");
      props.onRemoveSuccess && props.onRemoveSuccess(delData);
    } else if (res?.msgCode) {
      message.error(`${res?.resp_msg} || "删除失败",`);
    }
  };

  // 不能在props对象上直接添加属性,只能再定义一个attrs对象
  Object.assign(attrs, {
    action: "",
    accept: getAccepts(accept),
    disabled: disabled || loading,
    beforeUpload: (file) => beforeCheck(config, file),
    customRequest: async (opts) => {
      const { file, onSuccess } = opts;
      const formData = new FormData();
      formData.append("file", file);
      const list: any[] = Object.keys(data);
      if (list.length) {
        // 附带参数
        for (let item of list) {
          formData.append(item, data[item]);
        }
      }
      if (fileList.length) {
        const haveIdItem = fileList.find((item) => item.id);
        haveIdItem && formData.append("id", haveIdItem.id);
      }
       setLoading(true);
      const res = await request({
        url: config.url || "/exam/import-student",
        baseURL: env.compUrl,
        method: "post",
        data: formData,
      });
      setLoading(false);
      if (res?.msgCode == "200") {
        message.success("上传成功");
        props.onSuccess && props.onSuccess(res.data);
      } else if (res?.msgCode) {
        message.error(`${res?.resp_msg} || '上传失败'`);
      }
    },
    onPreview: (file) => handlePreview(file),
    showUploadList,
    onRemove: (file) => handleRemove(file),

    maxCount,
  });
   return (
    <>
      <Upload {...props} {...attrs}>
        {fileList.length < maxCount && !disabled ? (
          loading ? (
            <Spin size="small" />
          ) : (
            children
          )
        ) : null}
      </Upload>
      <Modal
        open={previewVisible}
        title={previewTitle}
        footer={null}
        onCancel={() => setPreviewVisible(false)}
      >
        <img alt="example" style={{ width: "100%" }} src={previewImage} />
      </Modal>
    </>
  );
};
export default UploadComponent;
//使用
<UpLoad
                disabled={type === "detail"}
                config={{
                  accept: "image",
                  data: { business_type: "article" },
                  url: "/v1/file/upload",
                  showUploadList: {
                    showRemoveIcon: type !== "detail",
                  },
                }}
                fileList={fileList}
                onSuccess={onUploadSuccess}
                onRemoveSuccess={onUploadRemove}
              >
               <Button
                  icon={<UploadOutlined />}
                  disabled={fileList.length >= 1}
                >
                  {"上传文章封面"}
                </Button>
              </UpLoad>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值