oss、huawei、亚马逊、monio文件上传方法封装

import request from 'utils/request';
import config from 'config/Config'

/**
 * 文件上传
 * @param {*} url 获取签名url
 * @param {*} file 上传文件
 * @param {*} callback 回调函数
 * @param {*} otherParams 其他参数
 * @param {*} type 上传类型 oss s3 huawei aws
 */
let uploadFn = (url = '', file = {}, callback, otherParams = {}, type = 'oss') => {
  url += `?fileType=${file.type}`;
  // bucketKey 云配置的桶,相当于命名空间 
  config.bucketKey && (url += `&&bucketKey=${config.bucketKey}`);
  let params = {
    ossType: getUploadType(type),
    url
  }
  getSgin(params).then(res => {
    if (`${res.resultCode}` === '0') {
      let fnMap = {
        huawei: huaweiUpload,
        s3: s3Upload,
        aws: awsUpload,
        oss: ossUpload,
      }
      fnMap[type](file, callback, otherParams, res.data)
    }
  })
}

// 获取上传类型
let getUploadType = (type) => {
  let typeEnum = {
    s3: 'MINIO',
    oss: 'ALIYUNOSS',
    huawei: 'HUAWEIOBS',
    aws: 'AMAZONS3'
  }
  return typeEnum[type]
}

// minio文件上传
let s3Upload = (file, callback, otherParams = {}, data = {}) => {
  let formData = new FormData();
  let key = calculate_object_name(data.key, 'home', file.name, false);
  Object.keys(data).forEach(item => {
    if (item === 'key' || item === 'form-action') return;
    formData.append(item, data[item]);
  })
  formData.append('key', `${key}${file.name}`);
  formData.append('file', file);
  beginUpload(data['form-action'], formData, otherParams, callback, file, `${key}${file.name}`);
}


// 亚马逊文件上传
let awsUpload = (file, callback, otherParams = {}, data = {}) => {
  let formData = new FormData();
  let key = calculate_object_name(data.key, 'home', file.name, false);
  Object.keys(data).forEach(item => {
    if (item === 'key' || item === 'form-action') return;
    formData.append(item, data[item]);
  })
  formData.append('key', `${key}${file.name}`);
  formData.append('file', file);
  beginUpload(data['form-action'], formData, otherParams, callback, file, `${key}${file.name}`);
}

// 华为文件上传
let huaweiUpload = (file, callback, otherParams = {}, data = {}) => {
  let formData = new FormData();
  let key = calculate_object_name(data.key, 'home', file.name, false);
  formData.append('x-obs-acl', data['x-obs-acl']);
  formData.append('content-type', file.type);
  formData.append('policy', data.policy);
  formData.append('key', key);
  formData.append('AccessKeyId', data.AccessKeyId);
  formData.append('signature', data.signature);
  formData.append('file', file);
  beginUpload(data['form-action'], formData, otherParams, callback, file, key);
}

// oss文件上传
let ossUpload = (file, callback, otherParams = {}, ossData = {}) => {
  let formData = new FormData();
  let ossKey = calculate_object_name(ossData.dir, 'home', file.name, false);
  formData.append('OSSAccessKeyId', ossData.accessid);
  formData.append('policy', ossData.policy);
  formData.append('signature', ossData.signature);
  formData.append('key', ossKey);
  formData.append('success_action_status', 200);
  formData.append('expire', ossData.expire);
  formData.append('file', file);
  beginUpload(ossData.host, formData, otherParams, callback, file, ossKey);
}

/**
 * 开始上传和成功后返回函数
 * @param {*} host 请求路径
 * @param {*} formData 数据
 * @param {*} otherParams 需要返回的参数
 * @param {*} callback 回调函数
 * @param {*} file 原文件
 * @param {*} key 上传文件名
 */
let beginUpload = (host, formData, otherParams, callback, file = {}, key) => {
  uploadInterface({
    url: host,
    formData
  }).then(result => {
    // 在axios.interceptors.response中做请求失败返回,以便确定请求失败,成功是不会有返回值的
    if (result) return;
    // 解决出现两个//
    host[host.length - 1] === '/' && (host = host.slice(0, -1));
    otherParams._result = `${host}/${key}`;
    otherParams.file = file;
    typeof callback === 'function' && callback(otherParams);
    console.log(`${host}/${key}`, 'result', otherParams)
    return otherParams;
  })
}

// 获取签名
let getSgin = (params = {}) => {
  return request({
    url: params.url,
    method: 'GET',
    headers: {
      ossType: params.ossType
    }
  })
}

// 上传文件
let uploadInterface = (params = {}) => {
  return request({
    url: params.url,
    method: 'POST',
    data: params.formData,
    headers: {
      "Context-Type": 'multipart/form-data '
    }
  })
}

let fileSuffix = (filename) => {
  const splitFile = filename.split('.')
  const len = splitFile.length
  return '.' + splitFile[len - 1]
}
let random = (n = 32) => {
  var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
  var letter = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'
  var maxPos = chars.length
  var result = ''
  for (var i = 0; i < n; i++) {
    result += chars.charAt(Math.floor(Math.random() * maxPos))
  }
  result = letter.charAt(Math.floor(Math.random() * letter.length)) + result
  return result.substring(0, result.length - 1)
}
// 混淆上传文件的名字
let calculate_object_name = (g_dirname, group, filename, isReal) => {
  if (!filename) {
    return ''
  }
  var suffix = fileSuffix(filename)
  var g_object_name = g_dirname + random(15) + suffix
  if (!!group && g_dirname) {
    if (g_dirname.indexOf('/') == -1) {
      g_dirname += '/'
    }
    g_object_name = decodeURIComponent(g_dirname + group + '/' + random(14) + suffix)
  }
  return g_object_name
}

export default uploadFn;

亚马逊完整参数

// 除了文件,其他数据由后端获取签名接口获取
x-amz-date: 20210309T080505Z
x-amz-signature: 'signature'
acl: 'acl'
x-amz-algorithm: 'x-amz-algorithm'
Content-Type: image/jpeg
x-amz-credential: 'x-amz-credential'
policy:  'policy'
key: '混淆文件名'
file: (binary)

minio完整参数

// 和亚马逊参数基本差不多
x-amz-date: 20210309T081113Z
x-amz-signature: 'x-amz-signature'
acl: 'acl'
x-amz-algorithm: AWS4-HMAC-SHA256
Content-Type: image/jpeg
x-amz-credential: 'x-amz-credential'
policy:  'policy'
key: '混淆文件名'
file: (binary)

需要注意的一个点

当配置了xhr.withCredentials = true时,必须在后端增加 response 头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。会造成上传文件地址如oss跨域。

如果在同域下配置xhr.withCredentials,无论配置true还是false,效果都会相同,且会一直提供凭据信息(cookie、HTTP认证及客户端SSL证明等)

  

如果你需要上传base64的图片,比如截图所得到的图片就是base64的图片,可以将base64图片转化为file图片,再进行上传,转换方法如下

/**
 * base64图片转成file图片
 * @param {*} dataurl base64图片完整路径
 * @param {*} filename 即将命名的文件名
 */
static base64ToFile = (dataurl, filename) => {
  var arr = dataurl.split(','),
    // 获取文件类型,如image/png
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime });
}

 

posted @ 2021-03-09 16:28  JSKevin  阅读(789)  评论(0编辑  收藏  举报