浪潮云对象存储(OSS)采坑记录

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/FYuu95100/article/details/99874879

浪潮云对象存储采坑记录

最近公司和浪潮有比较深度的合作,于是把很多业务迁移到浪潮云上,在迁移过程中踩了很多坑,在此记录一下,希望让后来的小伙伴们可以少踩点坑,也希望浪潮云业务越做越好,向阿里云、腾讯云看齐哈

    1. 简单介绍
  1. 业务介绍

        我们的业务是通过java的sdk把文件上传到浪潮云对象存储,并通过node的程序去读取文件里的一些信息并写入数据库,然后node后台再在适合的时机给前端该文件的URL地址

  1. 对象存储

        浪潮云的对象存储是OEMUCLOUD的,对象存储这些业务在阿里云叫OSS在浪潮云叫做UFile,一般问题可以咨询浪潮云的在线客服,或者是UCLOUD的在线客服,基本大多可以解决问题,但是可能有些业务UCLOUD的客服会不给游客解答,说是找不到你的资源id号

    1. 相关操作
  1. 创建存储空间

        在 浪潮云管理后台->对象存储->单地域空间管理 点击创建存储空间 创建存储空间(PS: 存储空间分私有空间和公共空间, 私有空间的访问路径需要带上公钥签名和过期时间,公共空间不用。但是截止我写这篇文章之前,即使是公共空间直接拼域名+文件名好像还会报签名错误)

  1. 创建公钥私钥

        这里公钥私钥有两种,一种是对象存储的公钥私钥,一种是API产品的公钥私钥,前者在 浪潮云管理后台->对象存储->令牌管理 创建令牌或者查看公钥私钥,后者在 API产品->API秘钥 处查看。前者的作用是通过SDK操作文件(上传 下载 删除 文件列表 图片处理),根据我们的需求,我创建了一个node的下载权限的令牌以及一个java的上传权限的令牌。后者的作用是生成文件访问URL时需要用到。(PS:这里创建令牌时需要注意授权存储空间,不然可能创建失败也没有提示,至于生成URL时需要的公钥秘钥我认为他这个对象存储的令牌按道理讲应该也是可以的,但是时间操作的时候的确不行,只有API产品秘钥生成的URL才是有效的)

  1. java上传文件

        java sdk 上传的话主要有这几个方法 PutFile(上传文件) PostFile(表单上传) UploadHit(秒传文件)。我这里用的是PutFile上传文件的方法

        java sdk 关于上传文件和秒传文件我还特意找客服了解过。秒传文件必须要UFile里存在才可以上传成功。如果没有会上传失败,感觉比较鸡肋。而上传文件遵循以下规则同名文件会覆盖,不同名的文件则视为两个文件,上传成功会返回文件的eTag,目前没有了解到有什么作用。后期其他sdk获取文件或者生产文件的URL需要使用的都是文件路径即上传的文件名。

        上传文件核心代码如下,需要注意的事项是 REGION(cn-inspur2) 和 PORXY_SUFFIX(ufileos.com) 这个两个参数是和客服沟通告诉我的, ObjectConfig 需要额外设置一下自定义域名setCustomHost 也是和客服沟通的。剩下就没什么了,上传成功会返回eTag和成功码,需要一提的是这时候需要记录一下上传文件的文件名。我们这边是java在发起http请求告知node程序的。(PS:Ufile的文件存储中不存在目录层级这一个概念,但是他有一个前缀的概念。可以认为前缀是xxx/的都是xxx目录下的文件,所以想要自己有目录层级需要自己拼存储路径的时候拼上,其实这个传参和阿里云OSS差不多不过阿里云OSS在其管理后台上明确有目录这个概念)

  private static final String PUBLIC_KEY = "对象存储令牌公钥";
  private static final String PRIVATE_KEY = "对象存储令牌私钥";
  private static final ObjectAuthorization OBJECT_AUTHORIZER = new UfileObjectLocalAuthorization(PUBLIC_KEY, PRIVATE_KEY);
  private static final String REGION = "cn-inspur2";
  private static final String PORXY_SUFFIX = "ufileos.com";
  private static final String BUCKET = "对象存储空间名";
  private static final String CUSTOM_HOST = BUCKET + ".infile.inspurcloud.cn"; //自定义域名
  public static boolean upload(File file) {
    ObjectConfig config = new ObjectConfig(REGION, PORXY_SUFFIX);
    config.setCustomHost(CUSTOM_HOST);// 需要设置自定义域名
    String md5 = null;
    String fileName = "prefix" + File.separator + md5 ;
  		BaseResponseBean response = UfileClient.object(OBJECT_AUTHORIZER, config)
        .putObject(file, MimeTypeUtil.getMimeType(file))
        .nameAs(fileName)
        .toBucket(BUCKET)
        /**
          * 是否上传校验MD5, Default = true
          */
        //.withVerifyMd5(false)
        .execute();
    String responseStr = response == null ? "null" : response.toString();// 上传结果
  1. node获取文件流
            java sdk把文件上传到浪潮云对象存储中后再通知node程序去处理文件。其中http请求的参数有url,eTag等,eTag目前不知道具体有什么用(可以确认文件是否相同),sdk获取文件流主要通过url去获取

        node代码如下通过拼接域名和文件名,请求头添加Authorization, Authorization是根据签名算法算出来的,具体可用参考UCLOUD文档中心API签名算法

const rp = require('request-promise');
const crypto = require('crypto');
const utf8 = require('utf8');
const Base64 = function(content) {
  return new Buffer(content).toString('base64');
}
const HmacSha1 = function(secretKey, content) {
  const hmac = crypto.createHmac('sha1', secretKey);
  hmac.update(content);
  return hmac.digest();
}
const UCloudPublicKey = "对象存储令牌公钥";
const UCloudPrivateKey = "对象存储令牌私钥";
const HTTPVerb = "GET";
const ContentMD5 = "";
const ContentType = "";
const MyDate = "";
const CanonicalizedUCloudHeaders = "";
const bucket = "对象存储空间名";

export async function getBufferByLcOss(url) {
  const key = url;
  const CanonicalizedResource = "/" + bucket + "/" + key;
  const StringToSign = HTTPVerb + "\n" + ContentMD5 + "\n" + ContentType + "\n" + MyDate + "\n" + CanonicalizedUCloudHeaders + CanonicalizedResource;
  const Signature = Base64(HmacSha1(UCloudPrivateKey, utf8.encode(StringToSign)));
  const Authorization = "UCloud" + " " + UCloudPublicKey + ":" + Signature;
  const urlstr = 'http://' + bucket + '.infile.inspurcloud.cn/' + key;
  console.log(urlstr, Authorization)
  const options = {
    uri: urlstr,
    method: 'GET',
    encoding: null,
    headers: {
      'Authorization': Authorization
    }
  };
  console.log(lsossConfig)
  const res = await rp(options).catch(err => console.log('err', err))
  console.log('res', res)
  return res;
  // request(options, callback)
  // .pipe(fs.createWriteStream(out_path));
}

  1. node生成URL访问地址

        node程序根据文件名生成文件的URL地址,和 node获取文件流 流程差不多,不过签名的过程有所不同,具体代码如下。基本步骤差不多 不过StringToSign拼接的参数有所区别,具体可用参考UCLOUD文档中心API签名算法。比较奇怪的是这里需要使用API产品公钥秘钥。



const rp = require('request-promise');
const crypto = require('crypto');
const utf8 = require('utf8');
const Base64 = function(content) {
  return new Buffer(content).toString('base64');
}
const HmacSha1 = function(secretKey, content) {
  const hmac = crypto.createHmac('sha1', secretKey);
  hmac.update(content);
  return hmac.digest();
}
const UCloudPublicKey = "API产品公钥";
const UCloudPrivateKey = "API产品秘钥";
const HTTPVerb = "GET";
const bucket = "对象存储空间名";

export async function getLcossUrl(url) {
  const key = url;
  const Expires = Math.round(new Date().getTime() / 1000) + 1800; //半个小时授权
  const CanonicalizedUCloudHeaders = "";
  var CanonicalizedResource = "/" + bucket + "/" + key;
  var StringToSign = HTTPVerb + "\n" +
    "\n" +
    "\n" +
    Expires + "\n" +
    CanonicalizedUCloudHeaders +
    CanonicalizedResource;
  var Signature = Base64(HmacSha1(UCloudPrivateKey, utf8.encode(StringToSign)));
 return `https://${bucket}.infile.inspurcloud.cn/${key}?UCloudPublicKey=${UCloudPublicKey}&Signature=${Signature}&Expires=${Expires}`;
}
    1. 相关文档资料
  1. 浪潮云对象存储文档
  2. 浪潮云对象存储上传文件文档
  3. UCLOUD文档中心UFile相关文档
  4. UCLOUD文档中心API签名算法
  5. java SDK
  6. node SDK
  7. sdk 下载界面

猜你喜欢

转载自blog.csdn.net/FYuu95100/article/details/99874879