美文网首页
前端(react)使用minio上传文件

前端(react)使用minio上传文件

作者: 时间煮鱼 | 来源:发表于2020-11-13 13:51 被阅读0次

借鉴代码

将上传代码封装成工具类

// 上传文件需要的配置
const Minio = require('minio');
const stream = require('stream');
// 你的minio配置信息
const minioClient = new Minio.Client(window.minioConfig);

// base64转blob
export function toBlob(base64Data) {
  let byteString = base64Data
  if (base64Data.split(',')[0].indexOf('base64') >= 0) {
    byteString = atob(base64Data.split(',')[1]); // base64 解码
  } else {
    byteString = unescape(base64Data.split(',')[1]);
  }
  // 获取文件类型
  const mimeString = base64Data.split(';')[0].split(":")[1]; // mime类型

  // ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区
  // let arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组
  // let uintArr = new Uint8Array(arrayBuffer) // 创建视图

  const uintArr = new Uint8Array(byteString.length); // 创建视图

  for (let i = 0; i < byteString.length; i += 1) {
    uintArr[i] = byteString.charCodeAt(i);
  }
  // 生成blob
  const blob = new Blob([uintArr], {
    type: mimeString
  })
  // 使用 Blob 创建一个指向类型化数组的URL, URL.createObjectURL是new Blob文件的方法,可以生成一个普通的url,可以直接使用,比如用在img.src上
  return blob;
};
/**
 * 上传文件 
 * @param {*} bucketName 桶名
 * @param {*} info info为antd上传组件的info
 * @param {*} callback 回调函数,返回下载url
 */
export function uploadFile(bucketName, info, callback) {
  // 获取文件类型及大小
  const fileName = info.file.name
  const mineType = info.file.type
  const fileSize = info.file.size
  // 参数
  const metadata = {
    "content-type": mineType,
    "content-length": fileSize
  }
  // 将文件转换为minio可接收的格式
  const reader = new FileReader();
  reader.readAsDataURL(info.file.originFileObj);
  reader.onloadend = e => {
    const dataurl = e.target.result;
    // base64转blob
    const blob = toBlob(dataurl);
    // blob转arrayBuffer
    const reader2 = new FileReader();
    reader2.readAsArrayBuffer(blob);
    reader2.onload = ex => {
      // 定义流
      const bufferStream = new stream.PassThrough();
      // 将buffer写入
      bufferStream.end(Buffer.from(ex.target.result));
      // 上传
      minioClient.putObject(bucketName, fileName, bufferStream, fileSize, metadata, err => {
        if (err == null) {
          // 获取可下载的url
          minioClient.presignedGetObject(bucketName, fileName, 24*60*60, (err1, presignedUrl) =>  {
            if (err1) return;
            // 将数据返回
            callback(presignedUrl);
          });
        }
      })
    }
  }
};
// 先判断桶是否存在, 如果可确保桶已经存在,则直接调用upload方法
export function checkedAndUpload(bucketName, info, callback) {
  minioClient.bucketExists(bucketName, err => {
    if (err) {
      minioClient.makeBucket(bucketName, 'us-east-1', err1 => {
        if (err1) {
          console.error(`${info.file.name}文件上传失败`);
          return ;
        }
        uploadFile(bucketName, info, callback);
      });
    } else {
      uploadFile(bucketName, info, callback);
    }
  });
}

在组件中调用

onChange = info => {
    const { dispatch } = this.props;
    const that = this;
    if (info.file.status !== 'uploading') {
      message.loading(`${info.file.name} 文件上传中,请等待`);
    }
    if (info.file.status === 'done') {
      checkedAndUpload('resources', info, res => {
        // 输出url
        message.success(`${info.file.name}文件上传成功`);
        const params = {
          url: res,
          key: that.state.uploadKey
        }
        console.log(res);
        dispatch(RESOURCES_UPLOAD(params))
      });
    } else if (info.file.status === 'error') {
      message.error(`${info.file.name}文件上传失败`);
    }
  };

  render() {
    // 上传组件 // 调用minio进行上传文件
    const uploadProps = {
      name: 'file',
      headers: {
        authorization: 'authorization-text',
      },
      onChange: this.onChange,
    };

    return (
      
        <Upload {...uploadProps}>
          <Button>
            <Icon type="upload" />
          </Button>
        </Upload>
    );
  }

相关文章

网友评论

      本文标题:前端(react)使用minio上传文件

      本文链接:https://www.haomeiwen.com/subject/lpbvbktx.html