资讯专栏INFORMATION COLUMN

图片直传阿里云OSS方案

imtianx / 923人阅读

摘要:和数据直传到相比,以上方法有三个缺点上传慢。端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。规定返回数据的格式,当前默认返回图片信息宽度高度,可获取更多数据。

背景

每个OSS的用户都会用到上传服务。Web端常见的上传方法是用户在浏览器或app端上传文件到应用服务器,然后应用服务器再把文件上传到OSS。

和数据直传到OSS相比,以上方法有三个缺点:

上传慢。先上传到应用服务器,再上传到OSS,网络传送比直传到OSS多了一倍。如果直传到OSS,不通过应用服务器,速度将大大提升,而且OSS采用BGP带宽,能保证各地各运营商的速度。

扩展性差。如果后续用户多了,应用服务器会成为瓶颈。

费用高。需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。

目的 Android、IOS端直传实践

Web端直传共有三种方式:

JavaScript客户端签名直传讲解在客户端通过JavaScript代码完成签名,然后通过表单直传数据到OSS。

服务端签名后直传讲解在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。

服务端签名直传并设置上传回调讲解在服务端通过PHP代码完成签名,并且服务端设置了上传后回调,然后通过表单直传数据到OSS。OSS回调完成后,应用服务器再返回结果给客户端。

在客户端通过JavaScript代码完成签名,无需过多配置,即可实现直传,非常方便。但是客户端通过JavaScript把AccesssKeyID 和AccessKeySecret写在代码里面有泄露的风险。

web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。然而有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用第三种方式。

本文将演示如何通过第三种方式完成文件直传到OSS服务器。

demo 前端
window.onload = function () {
    let upload = document.getElementById("upload")
    let link = document.getElementById("link")
    let obj = {}
    // 获取签名地址
    // const url = "http://gt-activity.gtdreamlife.com/api/oss/ossSign"
    axios.get(url).then(res => {
      if (res.data.statusCode === 200) {
          // 下面是签名直传服务返回给客户端的消息body内容的示例,这个body的内容将作为客户端上传文件的重要参数。
        let {
          dirPath,
          key,
          host,
          policy,
          Signature,
          callback,
          OSSAccessKeyId
        } = res.data.result
        obj.host = host
        obj.key = dirPath + key + "${filename}"
        obj.policy = policy
        obj.Signature = Signature
        obj.callback = callback
        obj.OSSAccessKeyId = OSSAccessKeyId
        console.log(obj)
      } else {
        alert(res.data.message)
      }
    })
    document.querySelector("#file").onchange = function (e) {
      let data = e.target.files[0]
      console.log(data)
      let formData = new FormData()
      for (let key in obj) {
        formData.append(key, obj[key])
      }
      // append 文件必须放在最后,不然会报key错误
      formData.append("file", data)
      axios.post(obj.host, formData).then(res => {
        const result = res.data
        document.querySelector("#link").value = result.data
      })
    }
  }
服务端

阿里云OSS配置信息

const config = {
  dirPath: "oss/file/", // oss 文件夹 不存在会自动创建
  bucket: "${bucket}", // oss应用名
  region: "${region}", // oss节点名
  accessKeyId: "${accessKeyId}", // 申请的osskey
  accessKeySecret: "${accessKeySecret}", // 申请的osssecret
  callbackPath: "api/oss/ossCallback", // 回调接口
  expAfter: 6000, // 签名失效时间
  maxSize: 1048576000, // 最大文件大小
};

获取签名接口
服务器返回数据Callback API

// 图片签名
  async ossSign() {
    const {
      bucket,
      region,
      expAfter,
      maxSize,
      dirPath,
      accessKeyId,
      accessKeySecret,
      callbackPath,
    } = config;
    const host = `https://${bucket}.${region}.aliyuncs.com`; // 你的oss完整地址
    // 回调接口的主机和端口
    const { callbackHost, callbackPort } = this.app.config.oss;
    const expireTime = new Date().getTime() + expAfter;
    const expiration = new Date(expireTime).toISOString();
    const policyString = JSON.stringify({
      expiration,
      conditions: [
        [ "content-length-range", 0, maxSize ],
        [ "starts-with", "$key", dirPath ],
      ],
    });
    const policy = Buffer(policyString).toString("base64");
    // 创建签名
    const Signature = crypto.createHmac("sha1", accessKeySecret).update(policy).digest("base64");
    const callbackBody = {
      // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
      callbackUrl: `https://${callbackHost}${callbackPort ? `:${callbackPort}` : ""}/${callbackPath}`,
      callbackHost: `${callbackHost}`,
      // 规定返回数据的格式,当前默认返回图片信息、宽度、高度,可获取更多数据。参考上方链接
      callbackBody: "{"filename": ${object},"size": ${size},"width": ${imageInfo.width},"height": ${imageInfo.height}}",
      callbackBodyType: "application/json",
    };
    const callback = Buffer(JSON.stringify(callbackBody)).toString("base64");
    this.ctx.body = ({
      statusCode: 200,
      message: "oss签名成功",
      result: {
        Signature, // 对变量policy签名后的字符串。
        policy, // 用户表单上传的策略(Policy),是经过base64编码过的字符串。
        host, // 用户要往哪个域名发送上传请求。
        OSSAccessKeyId: accessKeyId, // 用户请求的accessid。
        key: expireTime, // 唯一标识,添加到上传的文件名中防止重复
        success_action_status: 200,
        dirPath, // 文件上传地址
        callback, // 接口回调
      },
    });
  }

请求回调接口

// 回调
  async ossCallback() {
    const { body = {} } = this.ctx.request;
    // 对应签名接口中定义的返回数据字段
    const { filename, height, width } = body;
    if (filename) {
      this.ctx.body = ({
        status: 200,
        message: "操作成功",
        data: `https://${config.bucket}.${config.region}.aliyuncs.com/${filename}#w=${width}#h=${height}`,
      });
    } else {
      this.ctx.body = {
        status: 500,
        message: "操作失败",
        data: null,
      };
    }
  }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99025.html

相关文章

  • 阿里 oss 图片上传解决方案 vue (web直传

    摘要:我们通过这个去解决该文章主要介绍如何获取和这两个参数首先下载直传的案例解压后打开里面的完成后就可以用浏览器打开按下点到选项,效果如图我们随便选择一个图片上传然后配合来解决图片上传 我们通过aliyun-oss-web这个npm去解决 该文章主要介绍如何获取 imgSignature 和 imgPolicy 这两个参数 首先下载 web直传的案例 : http://files.cnblo...

    kyanag 评论0 收藏0
  • Web端文件上传至阿里OSS(基于Angular 5项目)

    摘要:一准备工作开通阿里云服务,从控制台上获取和。参考资料阿里云官方文档开始使用阿里云官方文档介绍如何在中快速使用访问服务微信公众号图片上传至阿里云前端图片直传试验如何基于和,快速搭建音视频文件上传服务声明转发请注明出处,谢谢 一、准备工作 1. 开通阿里云OSS服务,从控制台上获取AccessKeyId和AccessKeySecret。 2. 创建Bucket,并登录OSS控制台 3. 配...

    darkerXi 评论0 收藏0
  • oss web直传 服务器签名 - vue版本

    摘要:前言为了减轻服务器压力,采用直传的方式,直接把资源图片,文件,视频等上传到阿里云服务器。这个是需要触发这个回调来通知服务器操作结果。服务器端同事调的,通过接口返回给前端的。这个就是签名,最关键的。的的使用如下结束这样就搞定了。 前言: 为了减轻服务器压力,采用web直传的方式,直接把资源(图片,文件,视频等)上传到阿里云oss服务器。但是阿里只提供 plupload.js 环境下的 d...

    Sunxb 评论0 收藏0
  • 前端图片直传OSS试验

    摘要:当时的方案是前端先调用微信的选择图片并上传,然后再从后端下载到服务器上。如果其值未设置或者设置成一个非法值,返回一个空文档和状态码。所以,之前返回不正常的这个问题,只要强行指定返回状态码,就可以正常收到返回的了并且也没有先前报错的问题了。 前段时间参与了一个H5项目,里边有个需求是用户上传图片。当时的方案是前端先调用微信的JSSDK选择图片并上传,然后再从后端下载到服务器上。然而用的时...

    desdik 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<