背景介绍:

我司内部bbs平台支持用户发帖时上传视频。该功能前期上传速度慢+无法感知进度,经常被同事吐槽,加上公司内网不太稳定,故内网较慢时更加导致大家失去等待的耐心。经过团队同学的一番调研与优化,现在上传速度快+进度实时显示。那么这期间经历了什么?本文会跟大家分享下oss上传大附件的优化之路。

tips:本文提到的技术适用范围包括电商系统用户发表评论 / 贴吧系统用户发帖子 / 社交系统用户发布动态等等。

我们的初版架构如图:

前端->服务端上传至OSS->返回前端地址

优点:前端对接简单,通用性高,安全性高

缺点:有两次文件网络请求,占用服务器带宽,且上传速度慢

        该方案有个明显弊端是:前端无法感知到文件上传进度,只能使用假进度条并不断轮询后端接口查询上传结果,导致用户体感非常不友好。

       考虑到本系统是针对公司内部员工使用,在基于仅能内网访问+员工账号系统授权登录的前提下,我们考虑摒弃冗余的安全性校验,来换取传输速度的进一步提升。

新方案设计如下:

服务端签名->Web端直传至OSS流程

优点:占用服务器带宽少,且上传速度快,前端可获取到上传进度

缺点:流程前端部分操作相对较复杂,安全性相比服务端上传文件的方式低

前端效果:

动态效果:                                             

oss上传附件进度显示

前端实现:

// 上传文件                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
const changeUpload = (data: any) => {
    const formData = new FormData();
    formData.append("key", "xxx"); // 从服务端获取到的文件上传地址信息
    formData.append("policy", "xxx"); // 从服务端获取到的policy信息
    formData.append("signature", "xxx"); // 从服务端获取到的signature信息
    formData.append("OSSAccessKeyId", "xxx"); // 从服务端获取到的accessKeyId信息
    formData.append("file", data.file); // 从本地选择的文件,*注意:file一定要放在formData最后
    axios({
        url: "https://xxx.com", // 从服务端获取的endpoint地址信息
        data: formData,
        method: "POST",
        onUploadProgress: uploadProgress, // 文件上传进度回调, 选填
    }).then((res) => {
        console.log(res.status);
    });
}

/**
 * 上传进度回调
 * @param progressEvent
 */
const uploadProgress = (progressEvent: any) => {
  const { loaded, total } = progressEvent;
  const percentCompleted = Math.round((loaded * 100) / total);
  console.log(`当前上传进度 ${percentCompleted} %`)
};

 

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐