在日常的开发过程中,我相信大家肯定会碰到很多的文件上传需求,例如流程中的附件,设置头像图片等等内容,并且上传的文件,为了前端页面的加载性能,一般也都会选择将文件上传至云服务存储当中去,之后直接使用文件的 cdn 路径来访问。那么问题来了,对于文件如何上传到云服务存储当中去大家是否了解呢?上传流程有遇到什么困难吗,所以这篇文章也借着我们团队遇到的一些问题,跟大家交流一下云服务文件存储当中的一些问题与解决方式。

  不知道大家日常使用的上传方式是否和我们团队一致,之前上传文件方案中,我司后端团队会提供一个后端上传服务接口,前端直接使用这个接口进行文件上传,后端接受到完整文件后,会再通过调用云文件服务提供的后端 Java SDK 进行文件上传

小技巧-前端如何进行单文件上传云服务存储

  这个方案的优缺点

  优点:前端所有使用的上传接口统一,前端统一对接公司内部的上传服务,后端上传服务再去对接各个不同的云存储服务厂家,保证文件上传

  缺点:后端服务需要接受所有的文件上传的流量,然后再次进行上传,服务器压力比较大。

  基于上面提到的缺点,在经历过服务器压力过大,导致几次大文件上传失败、各种外地网络延迟导致超时故障之后,痛定思痛,决定要重新调整上传的方式。

  既然后端服务上传需要走流程传输导致资源压力过大,那是否可以可以将压力转移到用户侧,使用用户的浏览器直连云存储服务进行上传呢?答案是当然可以,不然也就没有本文了。

  在翻阅了几个不同的云服务的上传文档后发现,目前主流常用的前端上传方案会分为两种方式:前端调用各大云服务的 JavaScript SDK 进行上传优点:无需后端服务介入,直接调用各个云服务 SDK 方法使用即可缺点:前端需要获取各个云服务的 AK (AccessKey ID),SK (AccessKey Secret) 等账号信息,并且会暴漏在代码中,并且各个云服务场景会有对应的 SDK 以及调用方式,全部做了集成的话,包的体积可能不可控,并且有些云服务商,没有提供前端使用的SDK。云服务会提供临时授权的 URL,前端可以直接通过这个授权 URL 访问云服务,进行文件上传优点:前端不需要获取云服务的 AK (AccessKey ID),SK (AccessKey Secret) 信息,统一由后端接口提供对应上传所需的请求地址,数据格式即可,前端通过一个接口获取这些信息后,调用上传即可缺点:各家云服务上传所需的数据格式都不相同,前端需要调研,解析这个数据格式

  下面以大家常用的阿里云举例

  webpack打包类型项目,可以先通过 npm install ali-oss 安装 SDK,以下为上传数据到 examplebucket 中 exampledir 目录下的exampleobject.txt 文件的代码示例

  直接调用 SDK 中提供的 put 等方法即可完成文件上传

  鉴于 SDK 上传方案中,会在代码中暴漏 AK (AccessKey ID),SK (AccessKey Secret) 等云服务数据,所以云服务厂家一般也会提供生成临时令牌的方式,可以由后端服务生成一个自定义时效以及权限的访问凭证提供给前端进行上传,有效期到期后,这个访问令牌就会失效,保证了前端上传的安全性。

  1. 客户端向自己的后端应用发起请求,将文件类型,名称信息等传给后端,获取对应的上传信息以及授权签名信息 signature 等,

  2. 在获取到服务器返回的签名信息等内容后,客户端则可以通过 POST 或者 PUT 请求直接向云服务发送上传文件的请求(上传形式多种多样,并且有些云服务有要求上传数据类型为 form-data 格式)

  这里代码只是简单的示例,实际使用时需要对各个文件服务需要进行不同的适配。

  对于获取 Signature 鉴权信息等内容时,后端服务在有文档或者 SDK 时,可以对接不同的云服务 JAVA SDK 直接进行生成临时授权的信息,在没有文档的情况下,则需要前端或者后端,针对各个不同的云服务,进行解析加密 Signature 的步骤(我司这里是前端进行了加密过程解析后,后续日常生成由后端服务完成)。

  加密算法

  此处我以紫光云的 Signature 生成步骤给大家简单介绍下加密算法的流程,不同的云服务,加密过程都比较类似。

  图片来源:紫光云上传流程(https://www.unicloud.com/document/show-19262078.html)

  以下是根据上述的加密流程写的测试生成 Signature 的代码部分,大家也可以自行测试试用。

  按流程主要分成3步即可生成 CanonicalRequest 字段生成前面的 StringToSign根据 AK (AccessKey ID),SK (AccessKey Secret) 生成 Signature,最后组装 Authorization。

  常用云服务上传格式 下面也提供了一些常用云服务上传格式,上传需要的最基础格式,按照这个格式,组装出需要的数据,然后发起上传请求即可。下文示例中,如果使用 data 数据类型来进行校验权限,上传基本都是采用 form-data 数据封装,上传的 File 文件。而如果使用的是 headers 的类型进行数据校验,上传的 File 文件直接赋值请求中的 data 字段即可。

  阿里云

  华为云

  电信云 / 紫光云

  从这几种云服务的类型可以看出,上传参数区分,基本分为了data 数据校验上传或者 headers 校验上传,上面的文件上传实例代码基本可以包括目前的几种上传请求方式

  以上两种方式都可以满足前端直连上传的需求,大家选择的时候可以根据自己的实际场景进行选择即可。

  当你的上传云服务比较单一,无论是 SDK 上传,或者临时授权 URL 上传都可以选择,不过如果对账号安全比较敏感,第一种方式也可以选择加密或者配置数据的方式进行账号的传递。

  而鉴于我司有多种云服务上传的需求,并且 SDK 上传方式需要暴漏 AK (AccessKey ID),SK (AccessKey Secret) 等业务数据, SDK 的集成也会使后续输出的 NPM 包依赖内容过大,还需要兼容不同 SDK不同的上传调用方法,所以我司最后是选择了临时授权 URL 的方式进行处理,一方面,服务商敏感数据可以放在后端服务进行统一维护处理,另一方面,前端对于不同云服务上传的配置数据进行统一的兼容处理,在发起后续的上传,代码逻辑也会比较的统一。

  本文仅针对了单文件上传进行了梳理,对于多文件、分片上传等还未涉及,后续还会继续分享。不知道大家对于对接云服务上传是否还有其他更好的处理方式,欢迎一起讨论一下。

  阿里云 SDK 上传(https://help.aliyun.com/document_detail/383950.html)

  阿里云 PostObject 解析(https://help.aliyun.com/document_detail/31988.htm?spm=a2c4g.11186623.0.0.160750c5esmHVG#section-d5z-1ww-wdb)

  阿里云后端签名后直传(https://help.aliyun.com/document_detail/31926.html)

  华为云临时授权 url 访问(https://support.huaweicloud.com/sdk-browserjs-devg-obs/obs_24_0801.html)

  电信云鉴权加密方式(https://www.ctyun.cn/document/10026693/10027129)

  紫光云鉴权加密方式(https://www.unicloud.com/document/show-19262078.html)

  作者:季节

  来源:微信公众号:政采云技术

  出处:https://mp.weixin.qq.com/s/354U4xPAUoEKMv8mBJlRBw