需求
我们在日常的业务需求中,会大量的遇到视频,图片,文件等等的存储需求,目前接触到工具有:minio,obs,ftp等等。
本文主要介绍:华为云对象存储服务(Object Storage Service,简称OBS)为您提供基于网络的数据存取服务。使用OBS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种非结构化数据文件。
步骤
1.开通obs并官方文档配置obs。
2.参考官方api,在springboot集成obs。
一、开通obs并官方文档配置obs
登录华为云官网,在产品标签处直接搜索obs。
具体购买流程和购买后的配置请参考文档:
https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0001.html
华为云官方文档
二、springboot集成obs
1.创建测试工程,引入依赖。
2.在springBoot中集成OBS。
将密钥、 地址、桶名配置到application-dev.yml文件中,方便后期的更改。
创建对应的配置文件中华为账户对应的实体类。
分离出初始化obs方法。
结合官方文档封装自己的obs工具类。
package com.richstonedt.smartcity.xaytsccommoncs.util;
import com.obs.services.ObsClient;
import com.obs.services.ObsConfiguration;
import com.obs.services.exception.ObsException;
import com.obs.services.internal.ObsService;
import com.obs.services.model.*;
import com.richstonedt.smartcity.xaytsccommoncs.annotation.ObsClientAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* <b><code>ObsUtil</code></b>
* <p/>
* Description OBS工具类
* <p/>
* <b>Creation Time:</b> 2022/3/29 15:56:45
*
* @author tangjiahuan
* @since xaytsc-common-be
*/
public class ObsUtil {
private final static Logger logger = LoggerFactory.getLogger(ObsService.class);
private ObsClient obsClient;
private String bucketName;
private String bucketLoc;
private ObsConfiguration config;
public ObsUtil() {
}
public ObsUtil(String bucketName, String bucketLoc, ObsConfiguration config) {
this.bucketName = bucketName;
this.bucketLoc = bucketLoc;
this.config = config;
}
public ObsUtil( String bucketLoc, ObsConfiguration config) {
this.bucketLoc = bucketLoc;
this.config = config;
}
/**
* 查询所有桶
*
* @return 桶的列表
*/
// @ObsClientAnnotation
public List<ObsBucket> listBuckets() {
ListBucketsRequest request = new ListBucketsRequest();
request.setQueryLocation(true);
List<ObsBucket> buckets = obsClient.listBuckets(request);
return buckets;
}
/**
* 桶的新增
*
* @param bucketName 桶的名称
* @return 桶对象信息
*/
// @ObsClientAnnotation
public ObsBucket createBucket(String bucketName) {
ObsBucket obsBucket = new ObsBucket(bucketName, bucketLoc);
obsBucket.setBucketName(bucketName);
return obsClient.createBucket(obsBucket);
}
/**
* 桶的删除
*
* @param bucketName 桶的名称
* @return 响应对象
*/
// @ObsClientAnnotation
public HeaderResponse deleteBucket(String bucketName) {
return obsClient.deleteBucket(bucketName);
}
/**
* 设置桶内指定前缀的文件对象 过期时间
*
* @param prefix 什么前缀的文件过期(比如/tmp)
* @param expirationDays 几天后过期
*/
@ObsClientAnnotation
public HeaderResponse setLiftConfig(String prefix, Integer expirationDays) {
LifecycleConfiguration config = new LifecycleConfiguration();
LifecycleConfiguration.Rule rule = config.new Rule();
rule.setEnabled(true);
//过期规则名称
rule.setId(String.valueOf(UUID.randomUUID()));
rule.setPrefix(prefix);
LifecycleConfiguration.Expiration expiration = config.new Expiration();
// 指定满足前缀的对象创建x天后过期
expiration.setDays(expirationDays);
LifecycleConfiguration.NoncurrentVersionExpiration noncurrentVersionExpiration = config.new NoncurrentVersionExpiration();
// 指定满足前缀的对象成为历史版本x天后过期
noncurrentVersionExpiration.setDays(expirationDays);
rule.setNoncurrentVersionExpiration(noncurrentVersionExpiration);
config.addRule(rule);
return obsClient.setBucketLifecycle(bucketName, config);
}
/**
* 查询桶的所有对象
*
* @return 桶内对象集合(关键属性getObjectKey)
*/
// @ObsClientAnnotation
public ObjectListing listObjects() {
ObjectListing objects = obsClient.listObjects(bucketName);
return objects;
}
/**
* 上传对象时指定预定义访问策略为公共读(很重要)
*
* @param objectKey 对象的key
* @param inputStream 要上传的文件流
* @return 响应对象
*/
// @ObsClientAnnotation
public PutObjectResult putObjectAndSetPreAccessStrategy(String objectKey, InputStream inputStream) {
PutObjectRequest request = new PutObjectRequest();
request.setBucketName(bucketName);
//对象的key 如: objectname1/text
request.setObjectKey(objectKey);
request.setInput(inputStream);
//设置对象访问权限为公共读
request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
return obsClient.putObject(request);
}
/**
* 上传对象时指定预定义访问策略为公共读(很重要)
* @param isImage 是否为图片
* @param objectKey 对象的key
* @param file 要上传的文件
* @return 响应对象
*/
// @ObsClientAnnotation
public PutObjectResult putObjectAndSetPreAccessStrategy(String objectKey, File file,Integer isImage) {
PutObjectRequest request = new PutObjectRequest();
request.setBucketName(bucketName);
//对象的key 如: objectname1/text
request.setObjectKey(objectKey);
request.setFile(file);
//设置元数据 isImage 0:1:文件
ObjectMetadata metadata = new ObjectMetadata();
metadata.addUserMetadata("isImage", isImage.toString());
request.setMetadata(metadata);
//图片设置为公共读
/* if(isImage == 0){
//设置对象访问权限为公共读
request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
}*/
return obsClient.putObject(request);
}
/**
* 上传某个对象并设置对象自定义元数据
*
* @param objectKey 要上传的key
* @param metadata 元数据对象
* @param inputStream 要上传的文件流
* @return 上传结果
* // ObjectMetadata metadata = new ObjectMetadata();
* // metadata.addUserMetadata("property1", "property-value1");
* // metadata.getMetadata().put("property2", "property-value2");
* // C:\\Users\\hufanglei\\Pictures\\timg.jpg"
*/
// @ObsClientAnnotation
public PutObjectResult putObjectAndSetMeta(String objectKey, ObjectMetadata metadata, InputStream inputStream) {
return obsClient.putObject(bucketName, objectKey, inputStream, metadata);
}
/**
* 获取某个对象
*
* @param objectKey 对象的key
* @return 对象的信息
*/
// @ObsClientAnnotation
public ObsObject getObject(String objectKey) {
return obsClient.getObject(bucketName, objectKey, null);
}
/**
* 获取某个对象的流
*
* @param objectKey 对象的key
* @return 对象的流
*/
// @ObsClientAnnotation
public InputStream getObjectInpuStream(String objectKey) {
ObsObject obsObject = obsClient.getObject(bucketName, objectKey, null);
return obsObject.getObjectContent();
}
/**
* 查询对象元数据(查询某个对象的具体信息)
*
* @param objectKey 要查询的key
* @return 对象元数据
*/
// @ObsClientAnnotation
public ObjectMetadata getObjectMetadata(String objectKey) {
//获取对象元数据
return obsClient.getObjectMetadata(bucketName, objectKey, null);
}
/**
* 拷贝对象(也可以从一个桶拷贝到另一个桶,这里目前桶和原始文件桶都设置成了配置文件中的桶)
*
* @param sourceObjectKey 原始key
* @param destObjectKey 目标key
* @return 响应结果
*/
// @ObsClientAnnotation
public CopyObjectResult copyObject(String sourceObjectKey, String destObjectKey) {
String sourceBucketName = bucketName;
String destBucketName = bucketName;
return obsClient.copyObject(sourceBucketName, sourceObjectKey, destBucketName, destObjectKey);
}
/**
* 删除单个对象
*
* @param objectKey 要删除的key
* @return 响应结果
*/
// @ObsClientAnnotation
public DeleteObjectResult deletObj(String objectKey) {
return obsClient.deleteObject(bucketName, objectKey);
}
/**
* 删除 对象
* @param objectKey 对象key
* @return 是否删除成功
*/
public boolean deleteObject(String objectKey){
if(obsClient.doesObjectExist(bucketName,objectKey)){
obsClient.deleteObject(bucketName,objectKey);
return true;
}
return false;
}
public boolean isExistObject(String bucketName,String objectKey){
return obsClient.doesObjectExist(bucketName,objectKey);
}
/**
* 下载某个对象到本地
*
* @param objectKey 对象的key
* @param localFilePath 本地文件路径
* @throws ObsException
* @throws IOException
*/
// @ObsClientAnnotation
public void downloadToLocalFile(String objectKey, String localFilePath) throws ObsException, IOException {
File localFile = new File(localFilePath);
if (!localFile.getParentFile().exists()) {
localFile.getParentFile().mkdirs();
}
ObsObject obsObject = obsClient.getObject(bucketName, objectKey, null);
ReadableByteChannel rchannel = Channels.newChannel(obsObject.getObjectContent());
ByteBuffer buffer = ByteBuffer.allocate(4096);
WritableByteChannel wchannel = Channels.newChannel(new FileOutputStream(new File(localFilePath)));
while (rchannel.read(buffer) != -1) {
buffer.flip();
wchannel.write(buffer);
buffer.clear();
}
rchannel.close();
wchannel.close();
}
/**
* 创建一个文件夹,必须带有/后缀
*
* @param keySuffixWithSlash1 文件夹名称(必须带有/后缀)
* @return 响应对象
*/
// @ObsClientAnnotation
public PutObjectResult createEmptyFolder(String bucketName,String keySuffixWithSlash1) {
return obsClient.putObject(bucketName, keySuffixWithSlash1, new ByteArrayInputStream(new byte[0]));
}
/**
* 判断对象是否是文件夹
* @param keySuffixWithSlash1 文件夹名: 如: "MyObjectKey1/"
* @return 布尔值
*/
// @ObsClientAnnotation
public boolean isEmptyFolder(String keySuffixWithSlash1) {
ObsObject object = obsClient.getObject(bucketName, keySuffixWithSlash1, null);
if (object != null) {
return object.getMetadata().getContentLength() == 0L;
}
return false;
}
/**
* 列举某个文件夹下的所有对象
*
* @param folderPrefix 件夹名(必须/结尾)
* @return 对象集合
*/
// @ObsClientAnnotation
public ObjectListing listObjectsByFolder(String folderPrefix) {
ListObjectsRequest request = new ListObjectsRequest(bucketName);
// 设置文件夹对象名"dir/"为前缀
// request.setPrefix("dir/");
request.setPrefix(folderPrefix);
//列举文件个数
request.setMaxKeys(1000);
ObjectListing result;
do {
result = obsClient.listObjects(request);
for (ObsObject obsObject : result.getObjects()) {
logger.info("\t" + obsObject.getObjectKey());
logger.info("\t" + obsObject.getOwner());
}
request.setMarker(result.getNextMarker());
} while (result.isTruncated());
return result;
}
/**
* 删除某个文件夹下的所有对象
*
* @param folderPrefix 文件夹名(必须/结尾)
* @return 是否删除成功
*/
// @ObsClientAnnotation
public boolean deleteListObjectsByFolder(String folderPrefix) {
ListObjectsRequest request = new ListObjectsRequest(bucketName);
// 设置文件夹对象名"/xx/xxx/"为前缀
request.setPrefix(folderPrefix);
//列举文件个数
request.setMaxKeys(1000);
ObjectListing result;
do {
result = obsClient.listObjects(request);
for (ObsObject obsObject : result.getObjects()) {
logger.info("\t" + obsObject.getObjectKey());
logger.info("\t" + obsObject.getOwner());
//执行删除
obsClient.deleteObject(bucketName, obsObject.getObjectKey());
}
request.setMarker(result.getNextMarker());
} while (result.isTruncated());
return true;
}
/**
* 批量删除
* @param objectKeys 文件key集合
* @param bucketName 桶名
* @return 删除结果
*/
public DeleteObjectsResult deleteBatch(String bucketName,List<String> objectKeys){
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest();
for (String key:objectKeys) {
deleteObjectsRequest.addKeyAndVersion(key);
}
deleteObjectsRequest.setBucketName(bucketName);
return obsClient.deleteObjects(deleteObjectsRequest);
}
public void outputErrorInfo(ObsException e){
logger.info("HTTP Code: " + e.getResponseCode());
logger.info("Error Code:" + e.getErrorCode());
logger.info("Error Message: " + e.getErrorMessage());
logger.info("Request ID:" + e.getErrorRequestId());
logger.info("Host ID:" + e.getErrorHostId());
}
}
调用OBS工具类以及方法,将上传的文件传入到华为云OBS中。
上传obs成功后的资源如何如何访问。
测试
查看obs中是否上传成功。
查看obs上传成功后的返回地址是否可以访问。
- End-
收藏、点赞、转发,是对我最大的鼓励。您的支持就是我坚持下去的最大动力!
另外我的公众号也在同步更新文章。后续会更新SpringCloud alibaba开发实战、Elasticsearch+Logstash+Kibana实战、nginx+ssl+域名实战、日常开发问题闭坑集锦等等....