https://www.aliyun.com/product/oss/
开通对象存储 OSS
点击创建Bucket按钮,弹出创建Bucket界面
特别强调这里的读写权限一定设置为“公共的”。 北京地域、低频段存储
一般 访问外网 记录外网访问
Endpoint(地域节点) | Bucket 域名 | |
---|---|---|
外网访问(IPv4) | oss-cn-beijing.aliyuncs.com | hb20210830.oss-cn-beijing.aliyuncs.com |
外网访问(IPv4/IPv6) | cn-beijing.oss.aliyuncs.com | hb20210830.cn-beijing.oss.aliyuncs.com |
ECS 的经典网络访问(内网) | oss-cn-beijing-internal.aliyuncs.com | hb20210830.oss-cn-beijing-internal.aliyuncs.com |
ECS 的 VPC 网络访问(内网) | oss-cn-beijing-internal.aliyuncs.com | hb20210830.oss-cn-beijing-internal.aliyuncs.com |
新建目录
看懂说明文档 并 使用 https://help.aliyun.com/document_detail/51374.html?spm=5176.8465980.help.dexternal.41231450VMpKHN
查看目录 : 首页>对象存储 OSS>SDK 示例>Java
Maven 依赖(Java 9的话需更多)
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
点击: 开始使用子用户AccessKey
出现创建用户界面:输入登录用户名、显示用户名,勾选 编程访问,点击 确定即可创建用户。
若开通 Open API 调用访问,请及时保存 AccessKey 信息,页面关闭后将无法再次获取信息。
用户登录名称 | AccessKey ID | AccessKey Secret |
---|---|---|
0830_oos@1317924081557851.onaliyun.com | LTAI5tMoynAfAcojTgfU3fnF | PhzExMk0VrD7HeA8bzsz7lNkdmLoFG |
添加权限
上传文件流 Demo
public class OssDemo {
public static void main(String[] args) throws FileNotFoundException {
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "oss-cn-beijing.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "LTAI5tMoynAfAcojTgfU3fnF";
String accessKeySecret = "PhzExMk0VrD7HeA8bzsz7lNkdmLoFG";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
InputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\upload\\mimiup.png");
// 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
ossClient.putObject("hb20210830", "pic/mimiup.png", inputStream);
// 关闭OSSClient。
ossClient.shutdown();
}
}
上传的图片地址:https://hb20210830.oss-cn-beijing.aliyuncs.com/pic/mimiup.png bucket名.地域节点/文件目录
对比Bucket 域名:hb20210830.oss-cn-beijing.aliyuncs.com
每个 OSS 的用户都会用到上传服务。Web 端常见的上传方法是用户在浏览器或 APP 端上传文件到应用服务器,应用服务器再把文件上传到 OSS。具体流程如下图所示。
和数据直传到 OSS 相比,以上方法有三个缺点:
上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,可以节省应用服务器
创建模块 u-oss
添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos 客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- OSS 存储-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- SpringCloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
添加 Controller
@RestController
@RequestMapping("/oss")
public class UploadFileController {
@PostMapping("/upload")
public Map<String,String> upload(MultipartFile file) {
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "oss-cn-beijing.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "LTAI5tMoynAfAcojTgfU3fnF";
String accessKeySecret = "PhzExMk0VrD7HeA8bzsz7lNkdmLoFG";
String baseUrl = "https://hb20210830.oss-cn-beijing.aliyuncs.com/";
String originalFilename = file.getOriginalFilename();
String ext = StringUtils.getFilenameExtension(originalFilename);
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
// 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
String uri = "pic/"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+"."+ext;
ossClient.putObject("hb20210830",uri , inputStream);
System.out.println("文件访问路径"+baseUrl+uri);
// 关闭OSSClient。
ossClient.shutdown();
HashMap<String, String> map = new HashMap<>();
map.put("url",baseUrl+uri);
return map;
}
}
配置文件
server:
port: 10004
spring:
application:
name: oss
cloud:
nacos:
discovery:
server-addr: 192.168.159.130:8848
因为通过服务器上传 需要先到达服务器 时间长了一倍 但是直接上传 oss 也不可取 因为会暴露自己的密码参数
服务器端获取签名,客户端直接上传到oss原理
服务端签名后直传的原理如下:
参考官方文档:https://help.aliyun.com/document_detail/31926.htm
添加依赖 spring cloud 和 oss 整合包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
配置文件
server:
port: 10004
spring:
application:
name: oss
cloud:
nacos:
discovery:
server-addr: 192.168.159.130:8848
alicloud:
access-key: LTAI5tMoynAfAcojTgfU3fnF
secret-key: PhzExMk0VrD7HeA8bzsz7lNkdmLoFG
oss:
endpoint: oss-cn-beijing.aliyuncs.com
bucket: hb20210830
logging:
level:
com.offcn.oss: debug
写 新的 Controller UpdateByPolicyController
@RestController
@RequestMapping("/oss")
public class UpdateByPolicyController {
@Autowired
private 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;
@RequestMapping("/getPolicy")
public Map<String, String> upload() {
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
String formatDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = formatDate + "/"; // 用户上传文件时指定的前缀。
Map<String, String> respMap = new LinkedHashMap<String, String>();
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);
//封装accessid、签名等信息返回
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));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
} finally {
ossClient.shutdown();
}
return respMap;
}
}
启动服务,访问controller获取签名
访问地址:http://localhost:10003/oss/getPolicy
在前端工程renren-fast-vue目录src/utils/ 新建获取签名js文件 policy.js
import http from '@/utils/httpRequest.js'
export function policy () {
return new Promise((resolve) => {
http({
url: http.adornUrl('/oss/getPolicy'),
method: 'get',
params: http.adornParams({})
}).then(({ data }) => {
resolve(data)
})
})
}
配置网关
- id: oss-route
uri: lb://oss
predicates:
- Path=/api/renren-fast/oss/**
filters:
- StripPrefix=2
在前端工程renren-fast-vue目录src/views/modules/common目录下 创建上传页面 singleUpload.vue
注意:**修改下面 action属性 ** 指向oss存储桶地址:http://java0817-001.oss-cn-guangzhou.aliyuncs.com!
<template>
<div>
<el-upload
action="https://hb20210830.oss-cn-beijing.aliyuncs.com"
:data="dataObj"
list-type="picture"
:multiple="false" :show-file-list="showFileList"
:auto-upload="true"
:file-list="fileList"
:before-upload="beforeUpload"
:on-remove="handleRemove"
:on-success="handleUploadSuccess"
:on-preview="handlePreview">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MB</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="fileList[0].url" alt="">
</el-dialog>
</div>
</template>
<script>
import { policy } from '@/utils/policy'
import { getUUID } from '@/utils'
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
}]
},
showFileList: {
get: function () {
return this.value !== null && this.value !== '' && this.value !== undefined
},
set: function (newValue) {
}
}
},
data () {
return {
dataObj: {
policy: '',
signature: '',
key: '',
ossaccessKeyId: '',
dir: '',
host: ''
// callback:'',
},
dialogVisible: false
}
},
methods: {
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.policy
_self.dataObj.signature = response.signature
_self.dataObj.ossaccessKeyId = response.accessid
_self.dataObj.key = response.dir + getUUID() + file.name
_self.dataObj.dir = response.dir
_self.dataObj.host = response.host
// console.log(_self.dataObj)
resolve(true)
})
})
},
handleUploadSuccess (res, file) {
console.log('上传成功...')
this.showFileList = true
this.fileList.pop()
this.fileList.push({ name: file.name, url: this.dataObj.host + '/' + this.dataObj.key })
console.log(this.dataObj.host + '/' + this.dataObj.key)
this.emitInput(this.fileList[0].url)
}
}
}
</script>
<style>
</style>
在前端工程renren-fast-vue目录src/views/modules/question目录下 修改页面 type-add-or-update.vue
引入上传控件
import SingleUpload from '../../common/singleUpload' // 引入单文件上传组件
注册上传组件:
export default {
components:{ SingleUpload }
}
修改分类logo输入框,改成上传按钮
<el-form-item label="类型logo路径" prop="logoUrl">
<single-upload v-model="dataForm.logoUrl"></single-upload>
</el-form-item>
不成功
必须去设置 权限控制 跨域设置