龙空技术网

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

老码拾㻌 232

前言:

此刻咱们对“vueajax顺序”大体比较关切,朋友们都需要学习一些“vueajax顺序”的相关知识。那么小编也在网上搜集了一些有关“vueajax顺序””的相关内容,希望同学们能喜欢,你们一起来了解一下吧!

前面上传文件到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节复制的用户accessKeyIdstsAccessKeySecret: ***** //第一章第1节复制的用户AccessKeySecretstsRoleArn: 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访问密钥泄漏问题。

标签: #vueajax顺序