oss 存储方案
1 oss 基础配置
1 .1创建bucket
1.2 创建子账户
创建用户并授予编程访问权限:
创建用户成功后的样式:
1.3 授权
完成oss所有的权限
2 oss 官方文档地址
2.1 官方帮助文档:
https://help.aliyun.com/document_detail/32006.html
2.2 安装sdk
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
2.3 创建 springboot 项目测试
2.4 照片上传java后台
package com.liu.oss;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestComponent;
import java.io.FileInputStream;
import java.io.InputStream;
@SpringBootTest
public class UploadTest {
@Test
public void uploadOss() throws Exception {
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,
// Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,
// 请登录RAM控制台创建RAM用户。
String accessKeyId = "";
String accessKeySecret = "";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
InputStream inputStream = new FileInputStream("D:\\zhansan.jpg");
// 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。
// Object完整路径中不能包含Bucket名称。
ossClient.putObject("mart-mall", "abc/zhangsan.jpg", inputStream);
// 关闭OSSClient。
ossClient.shutdown();
}
}
2.4 测试结果
3 前端直接上传oss
3.1 服务器直传的缺点
首先说下,后端直接上传的缺点:
- 上传慢:用户数据需要先上传到应用服务器,之后再上传到oss中,网络传输时间比直传到oss多一倍时间。而直传到oss,速度姜大大提升。而且oss采用BGP带宽,能保证各个地区的传输速度。
- 拓展性差:如果用户多了,应用服务器将成为上传瓶颈
- 费用高:需要准备多台应用服务器,由于oss上传流量是免费的,不通过应用服务器
3.2 前端直传oss 上传模型
web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。如果想了解用户上传了什么,可以采用签名直传并设置上传回调。
3.3 参考文档
https://help.aliyun.com/document_detail/31923.html
3.4 服务器直传核心代码
package com.liu.oss.controller;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
@RestController
public class OssController {
public Map<String,String> policy() throws Exception {
String accessId = ""; // 请填写您的AccessKeyId。
String accessKey = ""; // 请填写您的AccessKeySecret。
String endpoint = "oss-cn-hangzhou.aliyuncs.com"; // 请填写您的 endpoint。
String bucket = "mart-mall"; // 请填写您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
String callbackUrl = "http://88.88.88.88:8888";
String dir = "user-dir-prefix/"; // 用户上传文件时指定的前缀。
// 创建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>();
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));
return respMap;
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return null;
}
}
3.5 获得policy
{
"accessid":"LTAI5t7EuTfR65tReySz6fdA",
"policy":"eyJleHBpcmF0aW9uIjoiMjAyMS0wOS0yNlQxMzowODowOS44NDlaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJ1c2VyLWRpci1wcmVmaXgvIl1dfQ==",
"signature":"GjGBWoH1REhM7IxGnMZ+ob97sdw=",
"dir":"user-dir-prefix/",
"host":"https://mart-mall.oss-cn-hangzhou.aliyuncs.com",
"expire":"1632661689"
}
4 创建前端工程项目
4.1 使用脚手架创建项目
4.2 集成 elementui
C:\Users\Administrator\upload-test>npm i element-ui -S
npm WARN deprecated core-js@2.6.12: core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.
added 9 packages in 10s
4.3 安装axios
C:\Users\Administrator\upload-test>npm install axios -S
added 1 package in 3s
4.4 配置axios
// @ts-nocheck
import axios from 'axios'
const request = axios.create({
baseURL: 'http://192.168.10.117:9008',
timeout: 5000
})
export default request
import request from '@/utils/requestoss'
// 获取policy请求地址
export function getPolicy() {
return request({
url: '/oss/policy',
method: 'get'
})
}
4.5 封装上传组件
<template>
<el-upload
class="upload-demo"
:action="objData.host"
:data="objData"
:before-upload="handleBefore"
:file-list="fileList"
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 { getPolicy } from '@/api/oss'
export default {
name: 'ossupload',
data() {
return {
objData: {
OSSAccessKeyId: '',
policy: '',
Signature: '',
key: '',
host: '',
dir: ''
},
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'
}
]
}
},
mounted() {},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList)
},
handlePreview(file) {
console.log(file)
},
handleBefore(file) {
console.log(file)
const _self = this
return new Promise((resolve, reject) => {
getPolicy()
.then(res => {
_self.objData.OSSAccessKeyId = res.accessid
_self.objData.policy = res.policy
_self.objData.Signature = res.signature
_self.objData.dir = res.dir
_self.objData.host = res.host
// eslint-disable-next-line no-template-curly-in-string
_self.objData.key = res.dir + '/' + '${ filename }'
resolve(true)
})
.catch(function(error) {
console.log(error)
reject(new Error(false))
})
})
}
}
}
</script>
<style lang="scss" scoped></style>
4.6 上传不成功
4.7 修正获取policy 接口,允许跨域
在controller接口上添加跨域注解
@CrossOrigin