基于react+antd +华为云OBS,写上传+图片预览

之前在网上也找不到Web具体实行OBS上传的代码,自己试着写了一下,感觉也还行,仅供参考,话不多说上代码

import * as React from "react";
import { Upload, Button, Icon, message, Modal } from "antd";
import "./uploads.less";

export default class UploadData extends React.Component<any, any> {
  constructor(props: any) {
    super(props);
    this.state = {
      loading: false,
      uploadData: {},
      fileList: [],
    };
  }
  componentDidMount() {
  }
  // 上传前的检验,指定上传类型,判断大小等
  beforeUpload = async (file, fileList) => {
    await this.getFileData();
    return new Promise((resolve, reject) => {
      if (file?.size > 1024 * 1024 * 1024) {
          message.error("请上传1G以内的文件");
          return reject(false);
        }
      
      return resolve(true);
    });
  };

  getFileType = (obj) => {
    let fileType = "Other";
    let mimeTypes = obj.type && obj.type.split("/")[0];
    if (mimeTypes === "image" || mimeTypes === 'Pic') {
      fileType = "Pic";
    } else if (mimeTypes === "video") {
      fileType = "Video";
    } else if (mimeTypes === "audio") {
      fileType = "Audio";
    }
    return fileType;
  };
  // 重点-上传方法
  upload = (data) => {
    const obsClient = new ObsClient({
      access_key_id: ‘ your  access_key_id’,
      secret_access_key: ‘your secret_access_key ’,
      server: ' your OBS  Endpoint',    //捅配置里面获取
    });
    // 设置表单参数
    var formParams = {
      // 设置对象访问权限为公共读
      'x-obs-acl': obsClient.enums.AclPublicRead,
      // 设置对象MIME类型
      'content-type': 'text/plain'
    };
    // 设置表单上传请求有效期,单位:秒
    var expires = 3600;
    var res = obsClient.createPostSignatureSync({ Expires: expires, FormParams: formParams });
    obsClient.putObject({
      Bucket: ' your Bucket', // 桶名称
      Key: `具体上传文件夹/${data.file.name}`,  // 桶 内对象文件存储地址  文件夹名称 +上传文件名
      SourceFile: data.file,
      Policy: res.Policy, // 策略
      Signature: res.Signature, //签名
      expires
    }, function (err, result) {
      if (err) {
      //此处上传失败后 可以调 data.onError 方法报错,upload 报错红色条,也可以在data 里面找到对应的方法改动
        console.error('Error-->' + err);
        data.onError()
      } else {
            //此处上传成功后 可以调 data.onSuccess() 更改文件上传对象的状态
        console.log('Status-->' + result.data);
        data.onSuccess()
      }
    })
  }
  // 整理数据,并传到表单
  sumbitData = () => {
    const { fileList } = this.state;
    const list = fileList.map((item) => {
      let obj = {
        fileType: this.getFileType(item),
        fileName: item.name,
        uri: item.response && item.response.url,
        previewUri: item.response && item.response.previewUrl,
        size: Number(item.size),
        ext: item.name && item.name.split(".")[1],
      };
      return obj;
    });
    this.props.onChange(list);
  };
  render() {
    const { singleFile, btnType, btnTitle, unIncon, value, remark, listType, isOnlyFile, accept, showUploadList } = this.props;
    let uploadType = listType || "text";
    let acceptType = accept || (listType === "picture-card" ? "image/*" : null);
    let showUploads = true;
    if (showUploadList === null || showUploadList === undefined) {
      showUploads = true;
    } else if (!showUploadList) {
      showUploads = false;
    }
    const uploadProps: any = {
      name: "file",
      beforeUpload: this.beforeUpload,
      multiple: !singleFile, // 默认true
      listType: uploadType,
      showUploadList: showUploads,
      customRequest: this.upload,  // 使用antd upload 重新定义上传方法
      fileList: this.state.fileList,
      onChange: (info) => {
        if (info.file.status === "done") {
          this.sumbitData();
        } else if (info.file.status === "error") {
          message.error(`${info.file.name} 上传失败.`);
        } else if (info.file.status === "removed") {
          this.setState({ fileList: info.fileList }, () => {
            this.sumbitData();
          });
        }
        if (isOnlyFile) {
          this.setState({
            fileList: [{
              ...info.file,
          }]
          });
        } else {
          let infoData = info
          this.setState({ fileList: infoData.fileList });
        }
      },
    };

    return (
      <div className="upload">
        <Upload {...uploadProps} accept={acceptType}>
          {uploadType === "text" && (
            <div>
              <Button type={btnType || "default"}>
                {unIncon ? null : <Icon type="upload" />}
                {btnTitle || "上传文件"}
              </Button>
              {remark && <span style={{ marginLeft: 15, marginTop: 5, fontSize: 12, color: "#999" }}>{remark || ""}</span>}
            </div>
          )}
          {uploadType === "picture-card" && (
            <div>
              <Icon type={this.state.loading ? "loading" : "plus"} />
              <div style={{ fontSize: "12px" }}>{btnTitle || "上传图片"}</div>
            </div>
          )}
        </Upload>
      </div>
    );
  }
}

less 样式

.upload {
  .file-item {
    display: flex;
    align-items: center;
    height: 32px;
    font-size: 14px;
  }
  .img-wrap {
    display: flex;
    flex-direction: row;
    align-items: center;

    .img-item {
      height: 64px;
      width: 64px;
      margin-right: 10px;
    }
  }

  .file-name {
    margin-left: 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-right: 15px;
  }

  .file-del {
    margin-left: auto;
  }
  .delete {
    cursor: pointer;
    &:hover {
      color: #099aff;
    }
  }
}

关于预览

因为考虑到安全问题,目前OBS内不支持浏览器直接预览。根据官方给的方法,就是要配置域名链接到桶内,开放公开权限才能使用域名来直接访问桶内上传的文件或者图片

在这里插入图片描述

所以浏览器预览上传OBS的图片或者文件只能使用域名来访问 。

示例: https://ceshiOBS.preview.cn/ceshiwenjian/${info.file.name} //域名是要配置证书的,没有在证书就使用http 。

如果有那种弹窗需要预览的,就要把这种URL 传入,才能访问到图片或者文件。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值