世界上最伟大的投资就是投资自己的教育

首页Ant Design Pro
随风 · 练气

ant design pro 如何使用阿里云直传的上传组件

随风发布于412 次阅读

如上图所示,

我们上传图片或文件到后端时,有两种方式

一种是直传到后端,另一种是用 oss 自带的 api

第一种会带我们自己的服务器带来消耗,假如你上传 1 G 的文件,这个时候你要带宽要比较大才顶得住。

如果用直传,就跟我们服务器没关了。

直传到阿里云,最后拿到它返回的地址,传到我们的自己数据库即可。

前端

组件我写好了


        <AliyunOSSUpload
          onFileUpload={(url: string) => {
            console.log('Uploaded file URL:', url);
            setImageUrl!(url);
          }}
          accept=".jpg,.jpeg,.png,.pdf"
          defaultFileList={defaultFileList}
        />

源码在此:

import React, { useEffect, useState } from 'react';
import { InboxOutlined } from '@ant-design/icons';
import type { UploadFile, UploadProps } from 'antd';
import { message, Upload } from 'antd';
import { FormattedMessage, request } from '@umijs/max';

interface OSSDataType {
  dir: string;
  expire: string;
  host: string;
  accessId: string;
  policy: string;
  signature: string;
}

interface AliyunOSSUploadProps {
  value?: UploadFile[];
  onChange?: (fileList: UploadFile[]) => void;
  accept?: string;
  onFileUpload: (url: string) => void;
  defaultFileList?: any;
}

const defaultAccept = '*';

const AliyunOSSUpload = ({
  value,
  onChange,
  accept,
  defaultFileList,
  onFileUpload,
}: AliyunOSSUploadProps) => {
  const [OSSData, setOSSData] = useState<OSSDataType>();

  // Fetch OSS Data from Backend API
  const fetchOSSData = async () => {
    try {
      const data = await request('/upload/get-oss-credentials'); // Adjust the endpoint as necessary
      setOSSData(data);
    } catch (error: any) {
      message.error(`Failed to get OSS data: ${error.message}`);
    }
  };

  useEffect(() => {
    fetchOSSData();
  }, []);

  const handleChange: UploadProps['onChange'] = ({ fileList }) => {
    console.log('Aliyun OSS:', fileList);
    if (fileList?.length > 0) {
      const lastFile = fileList[fileList.length - 1]; // 获取最后一个文件对象
      const lastFileUrl = lastFile.url;
      onFileUpload(lastFileUrl!);
    }
    onChange?.([...fileList]);
  };

  const onRemove = (file: UploadFile) => {
    const files = (value || []).filter((v) => v.url !== file.url);
    onChange?.(files);
  };

  const getExtraData: UploadProps['data'] = (file) => ({
    key: file.url,
    OSSAccessKeyId: OSSData?.accessId,
    policy: OSSData?.policy,
    Signature: OSSData?.signature,
  });

  const beforeUpload: UploadProps['beforeUpload'] = async (file: any) => {
    if (!OSSData) return false;

    const expire = Number(OSSData.expire) * 1000;
    if (expire < Date.now()) {
      await fetchOSSData();
    }

    const suffix = file.name.slice(file.name.lastIndexOf('.'));
    const filename = Date.now() + suffix;
    file.url = OSSData?.dir + filename; // Update file url to include the directory

    return file;
  };

  const uploadProps: UploadProps = {
    name: 'file',
    fileList: value,
    action: OSSData?.host,
    onChange: handleChange,
    onRemove,
    accept: accept || defaultAccept,
    data: getExtraData,
    beforeUpload,
  };

  return (
    <Upload.Dragger
      {...uploadProps}
      listType="picture"
      showUploadList={{ showRemoveIcon: true }}
      maxCount={1}
      style={{ width: 328 }}
      defaultFileList={defaultFileList}
    >
      <p className="ant-upload-drag-icon">
        <InboxOutlined />
      </p>
      <p className="ant-upload-text">
        <FormattedMessage
          id="upload_text"
          defaultMessage="Click or drag file to this area to upload"
        />
      </p>
    </Upload.Dragger>
  );
};

export default AliyunOSSUpload;

后端

后端只要获取 oss 的一些凭证就可以了

export const getOssCredentials = handleAsync(async (req: Request, res: Response) => {
  // Set the policy expiration time
  const policy = {
    expiration: new Date(new Date().getTime() + 60 * 60 * 1000).toISOString(), // Expires in 30 minutes
    conditions: [
      ['content-length-range', 0, 1048576000], // Limit upload size to no more than 1000MB
    ]
  };

  const result = await ossClient.calculatePostSignature(policy) as any;

  const host = `https://${process.env.OSS_BUCKET}.oss-cn-hongkong.aliyuncs.com`;

  res.json({
    accessId: process.env.OSS_ACCESS_KEY_ID,
    policy: result.policy,
    signature: result.Signature,
    host,
    dir: 'user-dir/',
    expire: new Date().getTime() + 30 * 60 * 1000, // Front-end use expiration time (milliseconds)
  });
})

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
喜欢
统计信息
    学员: 29811
    视频数量: 1987
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top