如何通过Web端直传文件(Object)到OSS

Web端上传OSS介绍

用户在浏览器或App端上传文件到应用服务器,应用服务器再把文件上传到OSS。具体流程如下图所示。

和数据直传到OSS相比,以上方法存在以下缺点:

  • 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS,网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
  • 扩展性差:如果后续用户数量逐渐增加,则应用服务器会成为瓶颈。
  • 费用高:需要准备多台应用服务器。由于OSS上行流量是免费的,如果数据直传到OSS,将节省多台应用服务器的费用。

本文主要介绍如何基于Post Policy的使用规则在服务端通过各种语言代码完成签名,然后通过表单直传数据到OSS。由于服务端签名直传无需将AccessKey暴露在前端页面,相比JavaScript客户端签名直传具有更高的安全性。

  1. 用户向应用服务器请求上传Policy和回调。
    let params =  {
           "expire": "xxx",
           "policy": "xxx",
           "signature": "xxx",
           "accessid": "xxx",
           "host": "xxx",
           "dir": "xxx"
         };
     axios.get('/getOssParams').then(result=>{
       params = result.data
     })
    
  2. 应用服务器(nodejs)返回上传Policy和签名给用户。
    var dayjs = require('dayjs');
    var crypto = require('crypto');
    var nanoid = require('nanoid');
     var config = {
       dirPath: "upload/",
       bucket: "xxx",
       region: "xxxx",
       accessKeyId: "xxxx",
       accessKeySecret: "xxxxx",
       expAfter: 1000*60*5, // 签名失效时间,毫秒
       maxSize: 1024*1000*1024*10, // 文件最大的 size B
     }
     // 过期时间
     const expire = new Date().getTime() + config.expAfter;
     const expiration = new Date(expire).toISOString();
    
     const dir = config.dirPath +dayjs().format('YYYY/MM/DD') + "/"  + nanoid.nanoid()
     // 上传文件名
     const policyString = JSON.stringify({
         expiration,
         conditions: [
           ["content-length-range", 0, config.maxSize],
           ["starts-with", "$key", dir],
         ],
       });
    
     const policy = Buffer.from(policyString).toString("base64");
    
     const signature = crypto
       .createHmac("sha1", config.accessKeySecret)
       .update(policy)
       .digest("base64");
    
     //返回参数
     const params = {
       expire,
       policy,
       signature,
       accessid: config.accessKeyId,
       host: "https://mukang.net",
       dir,
     };
    
  3. 用户直接向OSS发送文件上传请求。
  const files = document.querySelector('input[type="file"]')
  var formData = new FormData();
  const suffix =  files[0].name.slice(
     files[0].name.lastIndexOf(".")
  );
  const filename = Date.now() + suffix;

  formData.append("key", params.dir + "/" + filename);
  formData.append("policy", params.policy);
  formData.append("OSSAccessKeyId", params.accessid);
  formData.append("success_action_status", "200");
  formData.append("signature", params.signature);
  formData.append("file", files[0]);

  axios
    .post(params.host, formData, {
      headers: { "Content-Type": "multipart/form-data" },
      onUploadProgress: function (progressEvent) {
        console.log("进度", progressEvent.loaded / progressEvent.total);
      },
    })
    .then((result) => {
      console.log("result.data ===== ", params.hosts + '/' +  params.dir + filename);
    });

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值