oss直传

oss直传

this.file = new Map() //此处是用来存储数据

function upLoad(options, props) {
  const { file, onSuccess, onError, onProgress } = options
  const { fileSizeLimit, useInMonitor, onCallback } = props || {}

  const abort = () => {} //终止请求

  //第一步:查看文件是否限制,使用new window.file生成带size的文件
  if (fileSizeLimit && file.size > fileSizeLimit) {
    onError({
      success: false,
      message: `请上传${fileSizeLimit / (1024 * 1024)}M以下文件`,
    })
    return { abort }
  }

  //第二步:获取为未token时的文件信息
  const fileInfo = addFile(
    file,
    {
      status: 'pending',
      onError,
      onSuccess,
      onProgress,
      onCallback,
      retry: () => {
        this.setStatus(fileInfo.key, 'pending', {
          precent: 0,
          error: null,
        })
        this.simpleUpload(fileInfo, option)
      },
    },
    useInMonitor
  )
  //第三步:取到带token的地址
  simpleUpload(fileInfo, options)
}
function addFile(file, payload, indie) {
  let uuid = 0
  let noop = () => {}
  const fileInfo = {
    key: uuid++,
    file,
    ...payload,
    onerror: payload.onError || noop,
    onSuccess: payload.onSuccess || noop,
    onProgress: payload.onProgress || noop,
    onCallback: payload.onCallback || noop,
    cancel: () => {
      const info = this.getfile(key) //取消的时候找到对应的文件
      if (typeof info.xhr.abort === 'function') {
        info.xhr.abort()
      }
      this.reject(key, new Error('已取消上传'))
    },
    abort: () => {
      const info = this.getFile(key)
      if (!indie && typeof info.xhr.abort === 'function') {
        info.xhr.abort()
      }
      info.aborted = true
    },
  }
  this.file.set(key, fileInfo) //存储数据
  if (indie) {
    //此处为监听者的数据处理
    this.list.unshift(key)
    this.emiter.emit('addFile', fileInfo)
  }
  return fileInfo
}
function getOssToken() {
  const url = 'https://pre-dmt.alibaba-inc.com/portal/osstoken' //此处为oss直传url,视情况而定
  //此时为获取token参数的流程,详情见oss返回参数
  return GET(url, { method: 'GET' })
    .then((res) => {
      res.json()
    })
    .then((res) => {
      return res.data
    })
}
function simpleUpload(info, option) {
  const { file, headers, data } = option
  const id = info.key
  return getOssToken()
    .then((token) => {
      //token.dir为新地址的前缀,
      const pathName = [token.dir, getFileName(file)].join('')
      const xhr = entireUpload(token, {
        file,
        pathName,
        data,
        headers,
        onProgress: (ev) => {
          this.progress(id, ev)
        },
        //将成功返回的结果里添加自己想要的数据,做成功时的回调
        onSuccess: () => {
          const payload = {
            url: pathName,
            downloadUrl: `${token.host}/${pathName}`,
          }

          this.resolve(id, payload)
        },

        onError: (ex) => {
          this.reject(id, ex)
        },
      })
      info.xhr = xhr
      return info
    })
    .catch((ex) => reject(id, ex))
}

//带文件信息,带token上传
function entireUpload(
  token,
  { file, pathName, data, headers, onProgress, onSuccess, onError }
) {
    const xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    xhr.onerror = ex => {
      onError(ex);
    };
    if (xhr.upload) {
      xhr.upload.onprogress = function progress(ev) {
        if (ev.total > 0) {
          (ev).percent = (ev.loaded / ev.total) * 100;
        }
        onProgress(ev);
      };
    }
    xhr.onload = () => {
      // allow success when 2xx status
      // see https://github.com/react-component/upload/issues/34
      if (xhr.status < 200 || xhr.status >= 300) {
        return onError(new Error(xhr.statusText));
      }
  
      let result;
      try {
        result = JSON.parse(xhr.responseText || xhr.response);
      } catch {}
  
      onSuccess(result);
    };
  
    xhr.open('post', token.host, true);
  
    const formData = new FormData();
  
    if (data) {
      Object.entries(data).forEach(([key, value]) => {
        formData.append(key, String(value));
      });
    }
    formData.append('OSSAccessKeyId', token.accessid);
    formData.append('policy', token.policy);
    formData.append('Signature', token.signature);
    formData.append('key', pathName);
    // 成功后的状态码,默认是 204
    formData.append('success_action_status', '200');
    formData.append('file', file);
  
    // when set headers['X-Requested-With'] = null , can close default XHR header
    // see https://github.com/react-component/upload/issues/33
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    // if (headers['X-Requested-With'] !== null) {
    // }
    if (headers) {
      Object.entries(headers).forEach(([key, value]) => {
        xhr.setRequestHeader(key, String(value));
      });
    }
    xhr.send(formData);
    return xhr;
}

//以下关于处理的pathName仅为参考,可使用可不适用
function extname(fileName) {
  const pointIndex = fileName.lastIndexOf('.') //查找点最后一次出现的位置
  return [fileName.substr(0, pointIndex), fileName.substr(pointIndex)]
}
function getFileName(file) {
  const [fileName, ext] = extname(file.name)
  const name = encodeURIComponent(fileName)
    .replace(/[%\s]+/g, '')
    .substr(0, 16)
  return `${name}${Date.now().toString(32)}${ext}` //新拼接而成的地址
}

SDK=放着你想要的软件功能的软件包
API=SDK上唯一的接口

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值