生命的意义在于折腾

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

Web端上传OSS介绍

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

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

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

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

  1. 用户向应用服务器请求上传Policy和回调。

    javascript

    1let params =  {
    2       "expire": "xxx",
    3       "policy": "xxx",
    4       "signature": "xxx",
    5       "accessid": "xxx",
    6       "host": "xxx",
    7       "dir": "xxx"
    8     };
    9 axios.get('/getOssParams').then(result=>{
    10   params = result.data
    11 })
  2. 应用服务器返回上传Policy和签名给用户。

    javascript

    1var dayjs = require('dayjs');
    2var crypto = require('crypto');
    3var nanoid = require('nanoid');
    4 var config = {
    5   dirPath: "upload/",
    6   bucket: "xxx",
    7   region: "xxxx",
    8   accessKeyId: "xxxx",
    9   accessKeySecret: "xxxxx",
    10   expAfter: 1000*60*5, // 签名失效时间,毫秒
    11   maxSize: 1024*1000*1024*10, // 文件最大的 size B
    12 }
    13 // 过期时间
    14 const expire = new Date().getTime() + config.expAfter;
    15 const expiration = new Date(expire).toISOString();
    16
    17 const dir = config.dirPath +dayjs().format('YYYY/MM/DD') + "/"  + nanoid.nanoid()
    18 // 上传文件名
    19 const policyString = JSON.stringify({
    20     expiration,
    21     conditions: [
    22       ["content-length-range", 0, config.maxSize],
    23       ["starts-with", "$key", dir],
    24     ],
    25   });
    26
    27 const policy = Buffer.from(policyString).toString("base64");
    28
    29 const signature = crypto
    30   .createHmac("sha1", config.accessKeySecret)
    31   .update(policy)
    32   .digest("base64");
    33
    34 //返回参数
    35 const params = {
    36   expire,
    37   policy,
    38   signature,
    39   accessid: config.accessKeyId,
    40   host: "https://oss.mukang.net",
    41   dir,
    42 };
  3. 用户直接向OSS发送文件上传请求。

javascript

1  const files = document.querySelector('input[type="file"]')
2  var formData = new FormData();
3  const suffix =  files[0].name.slice(
4     files[0].name.lastIndexOf(".")
5  );
6  const filename = Date.now() + suffix;
7
8  formData.append("key", params.dir + "/" + filename);
9  formData.append("policy", params.policy);
10  formData.append("OSSAccessKeyId", params.accessid);
11  formData.append("success_action_status", "200");
12  formData.append("signature", params.signature);
13  formData.append("file", files[0]);
14
15  axios
16    .post(params.host, formData, {
17      headers: { "Content-Type": "multipart/form-data" },
18      onUploadProgress: function (progressEvent) {
19        console.log("进度", progressEvent.loaded / progressEvent.total);
20      },
21    })
22    .then((result) => {
23      console.log("result.data ===== ", params.hosts + '/' +  params.dir + filename);
24    });
25
阅读量:2474发布日期:2022-04-29 14:09:16

博客描述

OSS可用于图片、音视频、日志等海量文件的存储。各种终端设备、Web网站程序、移动应用可以直接向OSS写入或读取数据。OSS支持流式写入和文件写入两种方式。

留言板