VUE前端分片直传大文件到OSS方法

本文介绍了如何在Vue前端应用中使用阿里云STS服务进行大文件分片上传到OSS,避免了文件经由后端服务器转发,提高了效率并保障了安全性。详细步骤包括后台创建STS用户与账号、Spring Boot后台实现STS获取、Vue前端SDK的安装与使用,以及大文件分片上传的实现方法。

前面上传文件到OSS是使用的spring boot服务器上传,并搞定了大文件分片上传,但是在前后端分离的程序,使用这个方法效率存问题,用户浏览器先要将文件上传到运行VUE的nginx服务器,再转到spring boot应用服务器,然后再转到OSS服务器,要在服务器之间多转一次,会影响服务器效率。
后经同行提醒,阿里云OSS支持node.js SDK接口,可能在VUE服务器上,直接通过JS接口上传OSS服务器。
上传文件到OSS服务器,需要访问OSS的accessKeyId、accessKeySecret等重要访问密码,直接放到node.js服务器不安全,阿里云OSS提供了STS (Security Token Service) 进行临时授权访问方案,每一次产生一个有时间期限的临时访问Token,可以通过后台产生访问的Token,后台产生Token时先验证用户权限,有权限才能上传文件,这样解决了文件上传权限问题,也避免了在前端服务器上保存访问数据的敏感信息。原理如下,前端App端改为VUE应用服务器原理一样。
在这里插入图片描述
通过几天学习,完整的实现方案如下:

一、后台创建STS用户与帐号

需要提前在阿里云控制台创建好用户信息,并设置好权限。
1、创建访问用户
在这里插入图片描述
用户创建后,创建用户访问的AccessKeyId和accessKeySecret,注意这两个信息的保护,不能泄漏出去。
在这里插入图片描述
2、自定义权限策略
在这里插入图片描述
权限策略用脚本生成,如下所示,此权限策划包括对xiyoutianxia bucket的获取文件、列清单和上传文件权限。

{
    "Version": "1",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "oss:ListObjects",
                "oss:GetObject",
                "oss:PutObject"
            ],
            "Resource": [
                "acs:oss:*:*:xiyoutianxia",
                "acs:oss:*:*:xiyoutianxia/*"
            ]
        }
    ]
}

3、创建RAM角色
在这里插入图片描述
创建RAM角色,并在下一面将第2条设置的权限策略赋给此角色,这一步注意复制角色权限的ARN,图中右上。
在这里插入图片描述
4、将角权限制赋予给第1步创建的用户。
注意要添加下面2个权限,一个是标准的访问STS权限,一个是自己第3步定义的访问指定bucket的权限。
在这里插入图片描述

二、Spring Boot后台实现

1、添加依赖,添加下面3个依赖

<!-- 阿里云OSS -->
<dependency>
   <groupId>com.aliyun.oss</groupId>
   <artifactId>aliyun-sdk-oss</artifactId>
   <version>3.8.1</version>
</dependency>
<dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-sts</artifactId>
   <version>3.0.0</version>
</dependency>
<dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-core</artifactId>
   <version>4.4.6</version>
</dependency>

2、设置访问参数
我是将需要保密的访问参数,放到一个专门的配置文件,同时先报忽略上传git,避免密钥泄漏。

stsEndpoint: sts.cn-hangzhou.aliyuncs.com //注意与OSS的endPoint不一样
stsAccessKeyId: ***** //第一章第1节复制的用户accessKeyId
stsAccessKeySecret: ***** //第一章第1节复制的用户AccessKeySecret
stsRoleArn: acs:ram::1365080985****:role/ossst**** //第一章第3节复制的ARN信息

3、STS获取实现方法,放取utils 包中,注意此处的policy内容要在第一章第2节设置的策略范围以内,否则会报权限错误。

@Value("${aliyun.oss.stsEndpoint}")
private String stsEndpoint;
@Value("${aliyun.oss.stsAccessKeyId}")
private String stsAccessKeyId;
@Value("${aliyun.oss.stsAccessKeySecret}")
private String stsAccessKeySecret;
@Value("${aliyun.oss.stsRoleArn}")
private String stsRoleArn;

 /**
     * 生成OSS文件上传的需要的token生成
     *
     * @return STSToken
     */
    public AssumeRoleResponse getStsToken() {

        String roleSessionName = "quyouinfo";
        String policy = "{\n" +
                "    \"Version\": \"1\", \n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Action\": [\n" +
                "                \"oss:PutObject\",\n" +
                "                \"oss:GetObject\"\n" +
                "            ], \n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:xiyoutianxia\", \n" +
                "                \"acs:oss:*:*:xiyoutianxia/*\" \n" +
                "            ], \n" +
                "            \"Effect\": \"Allow\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        try {
            // 添加endpoint(直接使用STS endpoint,前两个参数留空,无需添加region ID)
            DefaultProfile.addEndpoint("", "", "Sts", stsEndpoint);
            // 构造default profile(参数留空,无需添加region ID)
            IClientProfile profile = DefaultProfile.getProfile("", stsAccessKeyId, stsAccessKeySecret);
            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(stsRoleArn);
            request.setRoleSessionName(roleSessionName);
            // 若policy为空,则用户将获得该角色下所有权限
            request.setPolicy(policy);
            // 设置凭证有效时间
            request.setDurationSeconds(1000L);
            final AssumeRoleResponse response = client.getAcsResponse(request);
            return response;
        } catch (ClientException e) {
            return null;
        }
    }

4、前端接口实现,注意用户token与权限验证,用系统统一的方案(过滤器)

/**
 * 获取VUE前端服务器上传OSS需要的token
 */
@ApiOperation("获取上传OSS的token")
@PreAuthorize("@ss.hasPermi('data:scenicfile:edit')")
@GetMapping("/getStsToken")
public AjaxResult getStsToken() {
    AssumeRoleResponse stsToken = ossFileUtils.getStsToken();
    AjaxResult ajax = AjaxResult.success(stsToken);
    return ajax;
}

三、VUE前端实现

1、安装SDK
使用npm安装SDK开发包,安装命令为npm install ali-oss --save。
2、使用时直接引用,不需要提前引用到全局方法
import OSS from ‘ali-oss’
3、普通文件直接上传,file是选取,或压缩转换后的文件对象

postImage(file) {
  //构建上传文件参数
  this.loading = true
  let user = this.$store.getters.name
  let self = this
  //获取上传文件所需要的STS Token
  getStsToken().then(response => {
    if (response.code === 200) {
      let token = response.data
      //直接通过node.js上传
      //console.log(token)
      let client = new OSS({
        region: 'oss-cn-hangzhou',
        accessKeyId: token.credentials.accessKeyId,
        accessKeySecret: token.credentials.accessKeySecret,
        stsToken: token.credentials.securityToken,
        bucket: 'xiyoutianxia',
        secure: true
      })
      let objectName = 'scenicfile/' + self.adcode + '/' + self.form.scenicId + '/' + user  + '/'  + file.name

      async function put() {
        try {
          //object-name可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
          let result = await client.put(objectName, file)
          //改阿里OSS后直接作用OSS路径前辍,不使用系统部署路径
          let shortUrl = result.url.substring(result.url.indexOf('scenicfile/'), result.url.length)
          self.imgUrl = process.env.VUE_APP_OSS_PREFIX + shortUrl
          self.msgSuccess('修改成功' + shortUrl)
          self.$emit('setUrl', shortUrl, self.file.name, self.location, self.takeTime)
          //console.log(result);
        } catch (e) {
          console.log(e)
        }
      }
      put()
    } else {
      this.msgError('OSS文件上传Token获取不成功!')
    }
    this.loading = false
  })
},

四、前端大文件分片上传

1 大文件分片上传,稍微复杂一下,需要先定义一个进度条

<div>
  <el-progress :text-inside="true" :stroke-width="18" v-if="percentage" :percentage="percentage"
               v-show="isProgressVis"></el-progress>
</div>

2 添加进度条与loading显示控制变量,在data中

//进度条
isProgressVis: false,
percentage: 0,
fileLoading:false,

3、大文件上传实现方法,采用的是同步执行方法

async uploadAudio(option) {
  try {
    if (this.form.scenicId !== null && this.form.scenicId !== undefined) {
      //构建上传文件参数
      let user = this.$store.getters.name
      this.fileLoading = true
      let self = this
      //获取上传文件所需要的STS Token
      let ret = await getStsToken()
      if (ret.code != '200') {
        throw new Error('获取OSS参数失败')
      }
      let token = ret.data
      let client = new OSS({
        region: 'oss-cn-hangzhou',
        accessKeyId: token.credentials.accessKeyId,
        accessKeySecret: token.credentials.accessKeySecret,
        stsToken: token.credentials.securityToken,
        bucket: 'xiyoutianxia',
        secure: true
      })
      let objectName = 'scenicfile/' + self.adcode + '/' + self.form.scenicId + '/' + user  + '/' + self.file.name
      // 分片上传文件
      let result = await client.multipartUpload(objectName, self.file, {
	     //进度条更新
		 progress: async function(p) {
          self.percentage = parseInt(p * 100)
          self.isProgressVis = true
        }
      })
      console.log(result)
      if (result.res.statusCode === 200) {
        //改阿里OSS后直接作用OSS路径前辍,不使用系统部署路径
        this.playerOptions.sources[0].src = process.env.VUE_APP_OSS_PREFIX + result.name
        this.msgSuccess('修改成功' + result.name)
        this.$emit('setUrl', result.name, this.file.name, '', '')
        this.fileLoading = false
        this.isProgressVis = false
      } else {
        this.$message.error('上传失败')
      }
    } else {
      this.$message.error('请先选择景区后上传文件!')
    }
  } catch (error) {
    this.$message.error(error.message)
  }
}

五、小结

通过node.js SDK从前端应用服务器直接上传OSS服务器,在大文件上传效率提升了很多,同时利用STS统一由后端业务服务器做权限控制,访问Token申请,有效避免了OSS访问密钥泄漏问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值