首页 > 其他分享 >接入阿里OSS后访问速度快了10倍

接入阿里OSS后访问速度快了10倍

时间:2023-01-30 11:00:09浏览次数:66  
标签:10 return 上传 OSS 访问速度 import com oss

问题场景
一个thymeleaf项目,上传图片、视频是直接使用Java代码保存到服务器上

于是服务器压力激增,网页静态资源变得卡顿

于是我们需要将图片、视频上传移植到阿里云OSS上

阿里云对象存储OSS(Object Storage Service)是阿里云提供的海量、安全、低成本、高持久的云存储服务。

一句话描述:它是一个很棒的存取文件的在线服务器

我们可以使用它进行客户端上传,文件不通过服务端也可以上传,这样减轻了我们服务端压力

我们需要一系列配置才可以对接完成,查阅阿里云OSS官方文档发现:JavaScript客户端签名直传的方式最为简单,但这种方式是有弊端的,客户端通过JavaScript把存取文件的认证信息写在代码里面有泄露的风险

因此我们采用服务端签名后直传的方式进行上传文件,我们待会儿介绍~

准备工作
登录阿里云官网

将鼠标移至产品,单击对象存储 OSS,打开 OSS 产品详情页面。

在 OSS 产品详情页,单击立即开通。

开通服务后,在 OSS 产品详情页单击管理控制台直接进入 OSS 管理控制台界面。

您也可以单击位于官网首页右上方菜单栏的控制台,进入阿里云管理控制台首页,然后单击左侧的对象存储 OSS 菜单进入 OSS 管理控制台界面。

根据官方文档提供步骤视频可以完成开通、创建Bucket、进行授权、配置跨域等 我们到阿里云RAM访问控制台来添加一个用户


添加用户
填入用户账号信息、勾选编程访问后点击确定


填入信息
然后我们点击复制,找个地方粘贴下来我们的AccessKey ID以及AccessKey Secret


复制密钥
然后我们点击添加权限为该用户授权


添加权限

选择权限

授权完成
开始对接
官方文档流程图片:
图片介绍
这里可以这么理解:

假设小王接到老板的任务:将这堆货物放到仓库中去,但仓库大门的门禁需要门卡

所以上图中的类比

1:小王去保管室拿门卡

2:小王拿到门卡回来

3:小王搬运货物到仓库,存放货物

因此我们首先先做“保管室”的功能

后端代码实现
这里就是用我们的Java代码在服务端实现:

引入alicloud-oss的依赖

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
application.yml,注意版本或者依赖不同,配置有可能改变,例如我最下面的Demo使用的boot的依赖(配置方式发生了变化,不过我们代码都还是一样的,只是注意@Value需要写对)

spring:
cloud:
alicloud:
access-key: <你的AccessKey>
secret-key: <你的SecretKey>
oss:
endpoint: <你的endpoint(可以在你的OSS控制台概览看到)>
bucket: <你的bucket(可以在你的OSS控制台概览看到)>
Controller

package com.ruben.simpleoss.controller;
import com.ruben.simpleoss.service.OssService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Map;
/**
* 上传Controller
*
* @author <[email protected]>
* @since 2021/6/18 17:40
*/
@RestController
public class UploadController {
@Resource
private OssService ossService;
/**
* oss上传文件
*
* @author <[email protected]>
* @since 2021/6/17 10:07
*/
@GetMapping("oss")
public Map<String, Object> oss() {
return ossService.getMark();
}
}

Service

package com.ruben.simpleoss.service;
import java.util.Map;
/**
* Oss服务层
*
* @author <[email protected]>
* @since 2021/6/17 10:21
*/
public interface OssService {
Map<String, Object> getMark();
}
ServiceImpl

package com.ruben.simpleoss.service.impl;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.ruben.simpleoss.service.OssService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @ClassName: UploadServiceImpl
* @Description: 获取OSS签证
* @Date: 2020/6/3 21:55
* *
* @author: achao<achao1441470436 @ gmail.com>
* @version: 1.0
* @since: JDK 1.8
*/
@Service
public class OssServiceImpl implements OssService {
@Resource
OSS ossClient;
@Value("${spring.cloud.alicloud.oss.endpoint}")
private String endpoint;
@Value("${spring.cloud.alicloud.oss.bucket}")
private String bucket;
@Value("${spring.cloud.alicloud.access-key}")
private String accessId;
/**
* 获取临时签证
*
* @return
*/
@Override
public Map<String, Object> getMark() {
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
// String callbackUrl = "http://88.88.88.88:8888";
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/"; // 用户上传文件时指定的前缀。
Map<String, String> respMap = null;
try {
long expireTime = 3000;
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(StandardCharsets.UTF_8);
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap = new LinkedHashMap<String, String>(8);
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 (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
Map<String, Object> result = new HashMap<>(4);
result.put("data", respMap);
result.put("code", 20000);
return result;
}
}

然后我们运行访问一下,就像第一步小王去拿门卡了

可以看到拿到我们的临时凭证了,就像第二步小王拿着门卡回来了


访问接口
然后我们现在要拿着这些凭证去上传文件,就像第三步小王要去存货物

按照PostObject的文档测试一下

上传完成之后我们这里是没有回调的,因为我们这里没有配置callback,如有需要,可以查看Callback文档


postman
上传完成之后我们可以在控制台看到我们上传的文件


上传完成看控制台
然后如果我们在代码里使用文件的url的话,就使用host+/+(key替换掉${filename}占位符为文件名)即可

例如我的host是https://will-deprecated.oss-cn-chengdu.aliyuncs.com

加上/再加上key为:2021-06-18/17585793-95b9-4dbd-8dfc-2302d6afa5df_${filename}替换掉文件名就是2021-06-18/17585793-95b9-4dbd-8dfc-2302d6afa5df_partnerhead.jpg(其实我测试过了,不用${filename}占位符,直接使用文件名也可以上传成功)

最终https://will-deprecated.oss-cn-chengdu.aliyuncs.com/2021-06-18/17585793-95b9-4dbd-8dfc-2302d6afa5df_partnerhead.jpg则是我们完整的文件路径

前端代码实现
使用html+vue

主页面,引用组件的地方

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OSS上传Demo</title>
<link href="/css/elementUI.css" rel="stylesheet">
<script src="/js/jquery-3.5.1.min.js"></script>
<script src="/js/vue.min.js"></script>
<script src="/js/elementUI.js"></script>
<script src="/js/singleUpload.js"></script>
</head>
<body>
<div id="myapp">
<single-upload ref="singleUpload" v-model="imageUrl"></single-upload>
文件url:{ {imageUrl} }
</div>
<script>
new Vue({
el: '#myapp',
data: {
imageUrl: ''
}
})
</script>
</body>
</html>

自己写的组件:

function policy() {
return new Promise((resolve, reject) => {
$.ajax({
url: '/oss',
type: 'GET',
contentType: 'application/json; charset=UTF-8',
success: function (res) {
if (res.code == 20000) {
resolve(res)
} else {
reject(res)
}
},
error: function (res) {
reject(res)
}
});
});
}
Vue.component('singleUpload', {
props: ['value'],
template: ' <div class="single-upload">' +
' <el-upload' +
' :before-upload="beforeUpload"' +
' :data="dataObj"' +
' :file-list="fileList"' +
' :multiple="false"' +
' :on-preview="handlePreview"' +
' :on-remove="handleRemove"' +
' :on-success="handleUploadSuccess"' +
' :show-file-list="showFileList"' +
' action="dataObj.host"' +
' list-type="text"' +
' style="display: flex;"' +
' >' +
' <el-button size="small" type="primary">点击上传</el-button>' +
' </el-upload>' +
' <el-dialog :modal="false" :visible.sync="dialogVisible">' +
' <img width="100%;" v-if="isImg(fileList[0].url)" :src="fileList[0].url" alt="图片找不到了..."/>' +
' <video width="900px" controls autoplay muted v-if="isVideo(fileList[0].url)" :src="fileList[0].url" alt="视频找不到了..."/>' +
' </el-dialog>' +
' </div>',
data() {
return {
dataObj: {
policy: "",
signature: "",
key: "",
ossaccessKeyId: "",
dir: "",
host: ""
// callback:'',
},
dialogVisible: false
};
},
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
}
];
},
showFileList: {
get: function () {
return (
this.value !== null && this.value !== "" && this.value !== undefined
);
},
set: function (newValue) {
}
}
},
methods: {
isVideo() {
let fileType = this.getFileType()
return ~['.mp4', '.avi'].indexOf(fileType)
},
isImg() {
let fileType = this.getFileType()
return ~['.png', '.jpg', '.jpeg', '.gif'].indexOf(fileType)
},
getFileType() {
let fileType = this.value.substring(this.value.lastIndexOf('.'))
return fileType
},
getUUID() { //生成UUID
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
})
},
emitInput(val) {
this.$emit("input", val);
},
handleRemove(file, fileList) {
this.emitInput("");
},
handlePreview(file) {
this.dialogVisible = true;
},
beforeUpload(file) {
let _self = this;
return new Promise((resolve, reject) => {
policy()
.then(response => {
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 + this.getUUID() + "_${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)
});
this.emitInput(this.fileList[0].url);
console.log(this.fileList[0]);
}
}
})

注意引入一些文件:


引入文件
最终效果:

演示效果1

演示效果2

演示效果3

演示效果4

演示效果5
项目源码
本次案例完整项目代码:https://gitee.com/VampireAchao/simple-oss.git

这个项目基本能应对绝大部分场景,它那次请求签证接口是使用的jQuery的ajax

如果您是纯vue项目,可以看我以往这个项目https://gitee.com/VampireAchao/my-vue-app.git

小结
通过对这次的OSS对接,复习了如何在html页面中引入vue、elementUI、引入vue自定义组件、进行第三方服务接入等...

大部分项目目前都接入了OSS,所以这是一个必须要掌握的技能!

文章编辑:学相伴阿超

KuangStudy首发:https://www.kuangstudy.com/bbs/1405846273780682753
————————————————
版权声明:本文为CSDN博主「狂神说」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33369905/article/details/118061953

标签:10,return,上传,OSS,访问速度,import,com,oss
From: https://www.cnblogs.com/baicaowei/p/17074834.html

相关文章

  • 让Windows Server 2008r2 IIS7.5 ASP.NET 支持10万并发请求
    由于之前使用的是默认配置,服务器最多只能处理5000个同时请求,今天下午由于某种情况造成同时请求超过5000,从而出现了上面的错误。为了避免这样的错误,我们根据相关文档调整了......
  • leetcode简单(矩阵):[566, 766, 832, 867, 999, 1030, 1261, 1275, 1337, 1351]
    目录566.重塑矩阵766.托普利茨矩阵832.翻转图像867.转置矩阵999.可以被一步捕获的棋子数1030.距离顺序排列矩阵单元格1260.二维网格迁移1275.找出井字棋的获胜者13......
  • 邮件端口25、109、110、143、465、995、993、994
    全部常用邮件端口25、109、110、143、465、995、993、994全部常用邮件端口有:25、109、110、143、465、995、993等,常见各大邮箱协议和端口见下方 1)发邮件协议和端口:A......
  • P1014 [NOIP1999 普及组] Cantor 表
    题目链接:https://www.luogu.com.cn/problem/P1014有理数可枚举In1873Cantorprovedtherationalnumberscountable,i.e.theymaybeplacedinone-onecorrespon......
  • 510cms网站上传大马
    首先用到命令sqlmap-u“网站地址”--os-shell,挂马之后,就可以使用linux命令了,同时可以看到下图的地址接着如下图,将选择好的php大马文件上传,页面显示uploaded就表示上传......
  • Adobe Flash Player 10.3.181.22 Final
    InternetExplorer:​​​http://fpdownload.macromedia.com/get/flashplayer/current/licensing/win/install_flash_player_10_active_x.exe​​Firefox,Safari,Opera:​......
  • 1013 Battle Over Cities
    1013BattleOverCities题目描述题意理解题意很简单,给出一张图,问如果去掉其中一个节点以及与这条节点相连的边,需要再添加几条边才能使图重新连通。解题的关键在于找......
  • 力扣110 平衡二叉树
    题目:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。示例:输入:root......
  • 前后端分离——使用OSS
    1.第一步:编写OSS的工具类点击查看代码aliyun:oss:keyid:填写自己的keysecret:填写自己的endpoint:填写自己的bucketname:填写自己的@Comp......
  • CF103E Buying Sets
    这个世界上怎么有这么巧妙的建模啊。。首先,题目保证了任意\(k\)个子集并的大小\(\gek\)。这说明我们选的数字的数量永远大于等于集合数量如果不考虑数字数量等于集......