1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 前后端分离整合阿里云OSS图片上传功能

前后端分离整合阿里云OSS图片上传功能

时间:2021-09-30 00:15:40

相关推荐

前后端分离整合阿里云OSS图片上传功能

传统上传方式

用户访问服务器,上传图片的操作由服务器完成。

缺点

大量请求访问服务器会造成很大的压力;在微服务中,必须要有一个统一固定的地方来存放文件资源,否则在多模块的微服务中,不能保证文件的正确性、一致性。

服务端签名后直传

前端请求服务器;服务器响应一个上传文件的签名给前端;前端拿着签名直接将需要上传的文件上传到oss中。

实现步骤

实现代码前确保在阿里云已经开通Oss存储功能,创建对应的bucket管理文件。

后端代码

导入依赖

<!-- oss --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alicloud-oss</artifactId><version>2.1.0.RELEASE</version></dependency>

编写controller层代码

@Controller@RequestMapping("/thirdparty/oss")public class OssController {@Autowiredprivate OSS ossClient;@Value("${spring.cloud.alicloud.access-key}")private String accessId;@Value("${spring.cloud.alicloud.oss.endpoint}")private String endpoint;@Value("${spring.cloud.alicloud.oss.bucket}")private String bucket;/*** 响应上传Policy和签名信息* @return Policy和签名信息*/@RequestMapping("/policy")@ResponseBodypublic R policy() {// 填写Bucket名称,例如examplebucket。// 填写Host地址,格式为https://bucketname.endpoint。String host = "https://" + bucket + "." + endpoint;// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。// String callbackUrl = "https://192.168.0.0:8888";// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。// 文件上传路径: 使用当前日期作为上传文件的目录String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());String dir = format + "/";Map<String, String> respMap = null;try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);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);respMap = new LinkedHashMap<String, String>();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));} catch (UnsupportedEncodingException e) {e.printStackTrace();}return R.ok().put("data", respMap);}}

该控制器的功能就是响应签名给前端,直接复制使用即可。

application.yml文件

右上角用户头像可以查看secret-key与access-key,如果没有请先点击创建。

发一个请求测试一下,是否能够拿到签名信息

前端代码

SingleUpload.vue

<template><div><el-upload:action="dataObj.host":data="dataObj"list-type="picture-card":multiple="false":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleUploadSuccess":on-preview="handlePictureCardPreview":limit="1":on-exceed="onExceed"><i class="el-icon-plus"></i></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="fileList[0].url" alt /></el-dialog></div></template><script>import {v4 as uuidv4 } from "uuid";export default {name: "singleUpload",props: {value: String},computed: {imageUrl() {return this.value;},imageName() {if (this.value != null && this.value !== "") {return this.value.substr(this.value.lastIndexOf("/") + 1);} else {return null;}},fileList() {return [{name: this.imageName,url: this.imageUrl}];}},data() {return {dataObj: {policy: "",signature: "",key: "",ossaccessKeyId: "",dir: "",host: ""// callback:'',},dialogVisible: false};},methods: {onExceed() {this.$message({type: 'error',message: '最多上传一张图片'});},emitInput(val) {this.$emit("input", val);},handleRemove(file, fileList) {console.log("handleRemove...");this.emitInput("");},handlePictureCardPreview(file) {console.log("show image...");this.dialogVisible = true;},beforeUpload(file) {console.log("start beforeUpload...");console.log("uuid", uuidv4());let _self = this;return new Promise((resolve, reject) => {this.$http.post("/thirdparty/oss/policy").then(result => {let response = result.data;console.log("响应的数据:", response);_self.dataObj.policy = response.data.policy;_self.dataObj.signature = response.data.signature;_self.dataObj.ossaccessKeyId = response.data.accessid;_self.dataObj.key = response.data.dir + uuidv4() + "_${filename}";_self.dataObj.dir = response.data.dir;_self.dataObj.host = response.data.host;resolve(true);}).catch(err => {reject(false);});});},handleUploadSuccess(res, file) {console.log("上传成功...");this.showFileList = true;this.fileList.pop();this.fileList.push({name: file.name,url:this.dataObj.host +"/" +this.dataObj.key.replace("${filename}", file.name)});console.log("image url:", this.fileList[0].url);this.emitInput(this.fileList[0].url);}}};</script>

这里使用了element-ui的上传组件。

页面

在页面导入组件。

当我们点击上传组件时,会执行beforeUpload方法,给服务器发送请求;服务器接收到请求会响应签名信息给前端;

前端拿到签名信息之后,会调用handleUploadSuccess方法,该方法中又调用了emitInput方法,携带签名信息直接向Oss请求上传文件。

测试,随便上传一个图片

这里在后端实现了上传的文件会存储到当前日期的文件夹中,如果有其他需要可以直接在后端代码中修改。

可能出现的问题:

5. 前端请求oss上传文件时,请求响应You have no right to access this object because of bucket acl.

- 检查后端controller配置是否有误,确保响应的请求host路径和签名信息正确。

- 检查阿里云AccessKey是否配置了权限。

6. 跨域访问

找到权限管理任务栏,拉到最底下,点击跨域设置

创建规则允许跨域即可

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。