VUE+EmelentUI实现-OSS前端直传后端签名
VUE+EmelentUI实现-OSS前端直传后端签名Web端上传介绍本文介绍如何通过Web端直传文件(Object)到OSS。---------------阿里云文档背景信息Web端常见的上传方法是用户在浏览器或App端上传文件到应用服务器,应用服务器再把文件上传到OSS。具体流程如下图所示。和数据直传到OSS相比,以上方法存在以下缺点:上传慢:用户数据需先上传到应用服务器,之后再上传到OSS,
VUE+EmelentUI实现-OSS前端直传后端签名
Web端上传介绍
本文介绍如何通过Web端直传文件(Object)到OSS。---------------阿里云文档
背景信息
Web端常见的上传方法是用户在浏览器或App端上传文件到应用服务器,应用服务器再把文件上传到OSS。具体流程如下图所示。
和数据直传到OSS相比,以上方法存在以下缺点:
- 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS,网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
- 扩展性差:如果后续用户数量逐渐增加,则应用服务器会成为瓶颈。
- 费用高:需要准备多台应用服务器。由于OSS上行流量是免费的,如果数据直传到OSS,将节省多台应用服务器的费用。
技术方案
目前通过Web端将文件上传到OSS,有以下三种方案:
-
利用OSS Browser.js SDK将文件上传到OSS
该方案通过OSS Browser.js SDK直传数据到OSS,详细的SDK Demo请参见上传文件。在网络条件不好的状况下可以通过断点续传的方式上传大文件。该方案在个别浏览器上有兼容性问题,目前兼容IE10及以上版本浏览器,主流版本的Edge、Chrome、Firefox、Safari浏览器,以及大部分的Android、iOS、WindowsPhone手机上的浏览器。----安全性差
-
使用表单上传方式将文件上传到OSS
利用OSS提供的PostObject接口,通过表单上传的方式将文件上传到OSS。该方案兼容大部分浏览器,但在网络状况不好的时候,如果单个文件上传失败,只能重试上传。操作方法请参见PostObject上传方案。
-
通过小程序上传文件到OSS
通过小程序,如微信小程序和支付宝小程序,利用OSS提供的PostObject接口来实现表单上传。操作方式请参见微信小程序直传实践和支付宝小程序直传实践。
Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但本示例中的服务端无法实时了解用户上传了多少文件,上传了什么文件。如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调(本地无法实现回调,oss回调需要服务器能被外网访问)。
流程介绍
- Web前端请求应用服务器,获取上传所需参数(如OSS的accessKeyId、policy、callback等参数)
- 应用服务器返回相关参数
- Web前端直接向OSS服务发起上传文件请求
- 等上传完成后OSS服务会回调应用服务器的回调接口(不实现)
- 应用服务器返回响应给OSS服务(不实现)
- OSS服务将应用服务器回调接口的内容返回给Web前端
后端签名实现
在Controller中写一个Mapping借口,实现前端对签名的访问
@RestController
public class OSSController {
@CrossOrigin //加上此注解实现跨域
@RequestMapping("/oss/policy")
public Map<String, String> policy() {
System.err.println("被请求了!");
String accessId = "LTAI5t8duBoMwvobqscKSLEU"; // 请填写您的AccessKeyId。
String accessKey = "0avav5Ha0sgvVyEThgIxSufZbRb9uk"; // 请填写您的AccessKeySecret。
String endpoint = "oss-cn-shanghai.aliyuncs.com"; // 请填写您的 endpoint。
String bucket = "my-tuling-oss"; // 请填写您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式为 BucketName.endpoint
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(new Date());
String dir = "前端直传测试/" + date + "/"; // 用户上传文件时指定的前缀。
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
// PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
Map<String, String> respMap = new LinkedHashMap<String, String>();
//阿里云oss前端直传必须参数
respMap.put("accessid", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
// respMap.put("expire", formatISO8601Date(expiration));
return respMap;
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return null;
}
}
此方法在阿里云的开发文档中可以找到—[传送门](Java (aliyun.com))
我们只需要进行简单的修改自己所需的必要参数即可
启动项目访问测试:eg:http://localhost:8088/oss/policy
VUE+ElementUI实现前端直传
1、设置阿里云Bucket的跨域规则
2、创建前端项目(假设已经懂得VUE,自己用ajax也可以)
1、初始化vue项目
1、提前将Vscode、nodejs等安装好。
2、全局安装vue-cli,vue-cli可以帮助我们快速构建Vue项目。
vscode终端安装命令:
npm install -g vue-cli
3、安装webpack,它是打包js的工具
安装命令:
npm install -g webpack
4、创建vue项目
首先创建一个文件夹用来存放你的项目,用vscode打开对应的文件夹,并在终端cd到对应的文件夹。比如我的文件夹就是myvue
创建命令:
vue init webpack myvue(这是你的项目名称)
接着会出现一些配置项,可以根据需要配置,也可以默认,直接按回车。
然后继续等待安装依赖项。完成之后,一个基本的 vue项目就搭建完了。完成之后的vscode左边可以看到如下目录,其中main.js就是入口。
5、运行项目:在终端目录为当前项目目录情况下输入以下命令
npm run dev
终端输出:
浏览器访问红色框中链接即可
6、题外话:项目打包发布上线
输入命令:
npm run build
完成之后,项目文件夹中会出现一个dist文件夹,里面就是打包之后的内容,直接部署就好了。
2、安装ElementUI(2.15.7版本)
官方文档:https://element.eleme.cn/#/zh-CN/
1、安装:
npm i element-ui -S
2、在项目src\components下建立组件:ossUpload.vue
/*
ElementUI上传组件版本:2.15.7
url:https://element.eleme.cn/#/zh-CN/component/upload
*/
<template>
<!-- -->
<el-upload
class="upload-demo"
:action="objData.host"
:file-list="fileList"
:data="objData"
:before-upload="ossPolicy"
list-type="picture"
>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
</template>
<script>
import axios from 'axios'
export default {
data () {
return {
fileList: [
{
name: 'food.jpeg',
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
},
{
name: 'food2.jpeg',
url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
}
],
objData: {
OSSAccessKeyId: '',
policy: '',
Signature: '',
key: '',
host: '',
dir: ''
}
}
},
methods: {
ossPolicy (file) {
alert('before-upload开始执行')
let _self = this
// return false直接停止上传
// 在上传之前进行服务器签名
return new Promise((resolve, reject) => {
// 请求后端(请求地址和后端访问地址一样)
axios
.get('http://localhost:8090/oss/policy')
.then(response => {
alert(JSON.stringify(response.data))
//获取前端参数
_self.objData.OSSAccessKeyId = response.data.accessid
_self.objData.policy = response.data.policy
_self.objData.Signature = response.data.signature
_self.objData.dir = response.data.dir
_self.objData.host = response.data.host
// eslint-disable-next-line no-template-curly-in-string
_self.objData.key = response.data.dir + '${filename}'
resolve(true) // 继续上传
})
.catch(function (error) {
alert(error)
console.log(error)
// reject(false)
reject(new Error(false)) // 停止上传
})
})
}
}
}
</script>
<style></style>
3、在项目中的HelloWorld.vue中使用ossUpload.vue组件
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li>
<a href="https://vuejs.org" target="_blank"> Core Docs </a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank"> Forum </a>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank">
Community Chat
</a>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank">
Twitter
</a>
</li>
<br />
<li>
<a
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
Docs for This Template
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a href="http://router.vuejs.org/" target="_blank">
vue-router
</a>
</li>
<li>
<a href="http://vuex.vuejs.org/" target="_blank"> vuex </a>
</li>
<li>
<a href="http://vue-loader.vuejs.org/" target="_blank">
vue-loader
</a>
</li>
<li>
<a href="https://github.com/vuejs/awesome-vue" target="_blank">
awesome-vue
</a>
</li>
</ul>
<!-- 使用上传模板组件 -->
<ul>
<li>
<OssUpload></OssUpload>
</li>
</ul>
</div>
</template>
<script>
// 导入上传组件
import OssUpload from '@/components/ossUpload'
// import OssUpload from './ossUpload.vue';
export default {
name: 'HelloWorld',
components: { OssUpload },
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
4、运行后端程序,运行前端程序
前端上传图片后:
后端控制台输出:
5、查看oss是否上传成功(我这里用的是oss browser查看的,和浏览器登录阿里云查看一样)
目录生成
图片如下
上传成功!
更多推荐
所有评论(0)