文件存储MinIO和AWS S3小demo

1,666 阅读2分钟

背景故事:

  • 公司项目需要给客户私有部署,原来的代码中文件存储用的是阿里云oss不能满足现有的需求。所以,技术上选用了MinIO。
  • 这里总结下自己调研后写的小demo。

代码部分

  • 由于MINIO 的 SDK,没有向外暴露上传下载进度事件,所以改用 AWS S3 官方API 连接后台的MinIo服务。

1.连接服务

class CloudStorage {
  constructor() {
    //通过S3连接MinIO
    this.s3 = new AWS.S3({
      apiVersion: "2006-03-01", //API版本
      endpoint: "http://192.168.5.47:9000", //后台服务地址
      accessKeyId: "admin", //登录连接用户
      secretAccessKey: "123456", // 密码
      s3ForcePathStyle: true, 
    });
    //其他配置
    this.bucket = "test"; // 存储桶名称
    this.dir = "mail"; //上传目录
    this.options = { partSize: 1000 * 1024 * 1024, queueSize: 1 };
  }
 }

2.单个文件上传

 /**
   * @description 单文件上传
   * @param {Object} file 文件对象
   * @param {Function} progressFn 进度函数,参数为进度数据
   * @returns Promise
   */
  upload({ file, progressFn }) {
    const self = this;
    return new Promise((resolve, reject) => {
      let params = {
        Bucket: this.bucket,
        Key: `${self.dir}/${new Date().getTime()}/${file.name}`,
        Body: file,
      };
      let uploader = self.s3.upload(params, self.options);
      //进度事件
      uploader.on("httpUploadProgress", (p) => {
        let progress = ((p.loaded / p.total) * 100).toFixed(0);
        progressFn(+progress);
      });
      uploader.send((err, data) => {
        if (err) {
          console.log("文件上传云存储失败", err);
          reject(err);
        } else {
          console.log("文件上传云存储成功", data);
          resolve({ data, state: 1, file });
        }
      });
    });
  }

3.批量上传

 /**
   * @description 多文件上传
   * @param {Object} files 文件对象集合
   * @param {Function} totelProgressFn 进度函数,参数为进度数据
   * @returns Promise
   */
  uploadFiles({ files, totelProgressFn }) {
    const self = this;
    return new Promise(async (resolve, reject) => {
      let tempArr = Array.from(files);
      let resArr = [];
      for (let i = 0; i < tempArr.length; i++) {
        const file = tempArr[i];
        let progressFn = function (data) {
          let uploadInfo = {
            index: i,
            name: file.name,
            progress: data,
          };
          totelProgressFn(uploadInfo);
        };
        let res = await self.upload({ file, progressFn });
        resArr.push(res);
      }
      resolve({ data: resArr, state: 1 });
    });
  }

4.下载文件

  // 下载文件
  downFile({ fileName, progressFn }) {
    const self = this;
    return new Promise((resolve, reject) => {
      let params = {
        Bucket: self.bucket,
        Key: fileName,
      };
      let downLoader = self.s3.getObject(params);
      downLoader.on("httpDownloadProgress", (p) => {
        let progress = ((p.loaded / p.total) * 100).toFixed(0);
        progressFn(+progress);
      });

      downLoader.send((err, data) => {
        if (err) {
          console.log("文件下载云存储失败", err);
          reject(err);
        } else {
          // 保存文件
          self.downLoadFile(data.Body, fileName);
          console.log("文件下载云存储成功", data);
          resolve({ data, state: 1 });
        }
      });
    });
  }

  //通过流下载文件
  downLoadFile(data, fileName) {
    const url = window.URL.createObjectURL(
      new Blob([data], {
        type: "application/octet-stream",
      })
    );
    const link = document.createElement("a");
    link.style.display = "none";
    link.href = url;
    link.setAttribute("download", fileName);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }

5.删除文件

  // 删除文件【支持批量】
  deleteFile(fileInfoArray) {
    console.log("fileInfoArray", fileInfoArray);
    const self = this;
    return new Promise((resolve, reject) => {
      var params = {
        Bucket: self.bucket,
        Delete: {
          Objects: fileInfoArray,
          Quiet: false,
        },
      };
      console.log("params", params);
      self.s3.deleteObjects(params, function (err, data) {
        if (err) {
          reject(err);
        } else {
          resolve({ data, state: 1 });
        }
      });
    });
  }

代码仓库

gitee