com.github.guang19.cosservice.template.objecttemplate.BaseTenCloudCOSObjectTemplate Maven / Gradle / Ivy
package com.github.guang19.cosservice.template.objecttemplate;
import com.github.guang19.cosservice.config.TenCloudCOSClientProperties;
import com.github.guang19.cosservice.util.COSUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;
/**
* @author yangguang
* @date 2020/2/3
* @description 腾讯云COS操作基础模板
*/
public abstract class BaseTenCloudCOSObjectTemplate implements TenCloudCOSObjectTemplate
{
//腾讯云COS客户端属性
private final TenCloudCOSClientProperties cosClientProperties;
//腾讯云cos操作高级接口
protected final TransferManager transferManager;
//cos 客户端
private final COSClient cosClient;
//当前模板地域
private String region;
//当前模板存储桶
private String objectTemplateBucket;
//存储拷贝对象时使用的TransferManager
private final Map copyTransferManagerMap = new ConcurrentHashMap<>();
//logger
protected final Logger logger = LoggerFactory.getLogger(BaseTenCloudCOSObjectTemplate.class);
/**
* 构造腾讯云COS对象操作基础模板
* @param cosClientProperties 腾讯云cos客户端属性
*/
protected BaseTenCloudCOSObjectTemplate(TenCloudCOSClientProperties cosClientProperties)
{
this.cosClientProperties = cosClientProperties;
this.region = cosClientProperties.getRegion();
this.objectTemplateBucket = getStandardBucketName(cosClientProperties.getObjectTemplateBucket());
this.cosClient = new COSClient(cosClientProperties.getCosCredentials(), COSUtil.newTenCloudCOSClientConfig(cosClientProperties));
this.transferManager = new TransferManager(cosClient,COSUtil.newThreadPoolExecutor(cosClientProperties));
this.copyTransferManagerMap.put(region,transferManager);
}
/**
*
* 获取当前存储桶下的所有对象的key,返回的对象包括目录和文件
* 返回的对象数量限制为1000
*
* @return 对象key集合
*/
@Override
public List getAllObjects()
{
return getAllObjectsWithKeyPrefix("");
}
/**
*
* 查询拥有相同前缀key的所有对象的key,返回的对象包括目录和文件
*
* @param keyPrefix 对象key前缀,如: img/ , file/upload/ , file/img/upload , file/img/upload/jquery.js(如果keyPrefix为文件,那么仅仅会返回这个文件)
* @return 对象key集合
*/
@Override
public List getAllObjectsWithKeyPrefix(String keyPrefix)
{
COSUtil.assertObjectNull(keyPrefix);
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName(objectTemplateBucket);
listObjectsRequest.setPrefix(keyPrefix);
listObjectsRequest.setDelimiter("");
listObjectsRequest.setMaxKeys(1000);
LinkedList keys = new LinkedList<>();
String nextMarker = null;
ObjectListing objectListing = null;
try
{
do
{
objectListing = cosClient.listObjects(listObjectsRequest);
objectListing.getObjectSummaries().forEach(cosObjectSummary -> keys.add(cosObjectSummary.getKey()));
nextMarker = objectListing.getNextMarker();
listObjectsRequest.setMarker(nextMarker);
}while (objectListing.isTruncated());
}
catch (CosClientException e)
{
logger.error("error during cos client batch get object : ".concat(e.getMessage()));
}
finally
{
close();
}
return keys;
}
/**
*
* 获取当前存储桶下的所有文件名
*
*
* @return 文件名集合
*/
@Override
public List getAllFileNames()
{
return getAllFileNamesWithKeyPrefix("");
}
/**
*
* 查询拥有相同前缀key的所有文件名
*
*
* @param keyPrefix 文件key前缀,如: img/ , file/upload/ , file/img/upload , file/img/upload/jquery.js(如果keyPrefix为文件,那么仅仅会返回这个文件)
* @return 文件名集合
*/
@Override
public List getAllFileNamesWithKeyPrefix(String keyPrefix)
{
return getAllObjectsWithKeyPrefix("")
.parallelStream()
.filter(key -> !key.endsWith("/"))
.map(key->
{
String[] splitArr = key.split("/");
return splitArr[splitArr.length - 1];
})
.collect(Collectors.toList());
}
/**
* 获取所有文件的key
*
* @return 文件key集合 : img/a.jpg , img/a/b/c.jpg , d.jpg
*/
@Override
public List getAllFileKeys()
{
return getAllObjectsWithKeyPrefix("")
.stream()
.filter(key -> !key.endsWith("/"))
.collect(Collectors.toList());
}
/**
* 获取对象的元信息
* @param key 对象key
* @return 对象元信息键值对
*
* ETag: xxxxxxxxxxxxxxxxxx
* Connection: keep-alive
* x-cos-request-id:xxxxxxxxxxxxxxxxxxxx
* Last-Modified :Wed Sep 25 16:22:02 CST 2019
* Content-Length :1024
* Date :Tue, 04 Feb 2020 05:03:03 GMT
* Content-Type :image/png
*
*/
@Override
public Map getObjectMetaData(String key)
{
COSUtil.assertObjectNull(key);
Map metadata = null;
try
{
ObjectMetadata objectMetadata = cosClient.getObjectMetadata(objectTemplateBucket, key);
if(objectMetadata != null)
{
metadata = objectMetadata.getRawMetadata();
}
}
catch (CosClientException e)
{
logger.error("error during get object metadata : ".concat(e.getMessage()));
}
finally
{
close();
}
return metadata;
}
/**
* 上传文件到存储桶的默认目录
*
* @param filePath 本地文件路径
* @return 上传成功后, 对象的url
*/
@Override
public String uploadFile(String filePath)
{
throw new UnsupportedOperationException("can not upload file with base template");
}
/**
* 上传文件到存储桶
*
* @param cosDir 需要将对象上传到存储桶的哪个目录,必须以 '/' 结尾,允许空串
* @param filePath 本地文件路径
* @return 上传成功后, 对象的url
*/
@Override
public String uploadFile(String cosDir, String filePath)
{
throw new UnsupportedOperationException("can not upload file with base template");
}
/**
* 上传对象到存储桶的默认目录
*
* @param fileStream 对象的输入流
* @param objectName 指定上传后的对象名,但不需要指定后缀,如: a.jpg, a , b.jpg , b , cat 都行
* @return 上传成功后, 对象的url
*/
@Override
public String uploadFile(InputStream fileStream, String objectName)
{
throw new UnsupportedOperationException("can not upload file with base template");
}
/**
* 上传对象到存储桶
*
* @param fileStream 对象的输入流
* @param cosDir 需要将对象上传到存储桶的哪个目录,必须以 '/' 结尾,允许空串
* @param objectName 对象名,但不需要指定后缀,如: a.jpg, a , b.jpg , b , cat 都行
* @return 上传成功后, 对象的url
*/
@Override
public String uploadFile(InputStream fileStream, String cosDir, String objectName)
{
throw new UnsupportedOperationException("can not upload file with base template");
}
/**
* 下载文件到本地
*
* @param key 文件的key
* @param saveFile 指定下载后的文件,这个文件不需要存在
* 比如你需要下载的文件key为: img/a.jpg,
*
* 那么你可以指定filepath为 :
*
* a.jpg
*
* b.jpg")
*
* /usr/dir/img.jpg
*
*
无需指定下载的文件类型
* /usr/dir/a
*
* G:/dir/b
*/
@Override
public void downloadFile(String key, String saveFile)
{
throw new UnsupportedOperationException("can not download file with base template");
}
/**
*
* 把当前存储桶下的所有文件都下载到本地
* 此方法的耗时取决于当前存储桶的文件数量和文件大小
*
* @param saveDir 指定本地目录
*/
@Override
public void downloadAllFiles(String saveDir)
{
throw new UnsupportedOperationException("can not download file with base template");
}
/**
* 根据对象key删除当前存储桶下的对象
*
* @param key 对象的key
*/
@Override
public void deleteObjectWithKey(String key)
{
COSUtil.assertObjectNull(key);
try
{
cosClient.deleteObject(objectTemplateBucket,key);
}
catch (CosClientException e)
{
logger.error("error during delete object : ".concat(e.getMessage()));
}
finally
{
close();
}
}
/**
* 根据对象键集合,批量删除当前存储桶下的对象
*
* @param keys 对象键集合
*/
@Override
public void deleteObjectsWithKeys(List keys)
{
COSUtil.assertListEmpty(keys);
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(objectTemplateBucket);
deleteObjectsRequest.setKeys(keys.stream().map(DeleteObjectsRequest.KeyVersion::new).collect(Collectors.toList()));
try
{
cosClient.deleteObjects(deleteObjectsRequest);
}
catch (CosClientException e)
{
logger.error("error during cos client batch delete object : ".concat(e.getMessage()));
}
finally
{
close();
}
}
/**
* 根据url删除当前存储桶对象
*
* @param url 对象的url
*/
@Override
public void deleteObjectWithUrl(String url)
{
COSUtil.assertObjectNull(url);
String domainPrefix = COSUtil.getTenCloudObjectUrlPrefix(objectTemplateBucket,region);
if(!url.startsWith(domainPrefix))
{
throw new IllegalArgumentException("url must be tencent cloud url and region and bucket must be reasonable");
}
else
{
deleteObjectWithKey(url.replace(domainPrefix,""));
}
}
/**
* 根据url集合,批量删除当前存储桶对象
*
* @param urls url集合
*/
@Override
public void deleteObjectsWithUrls(List urls)
{
COSUtil.assertListEmpty(urls);
String domainPrefix = COSUtil.getTenCloudObjectUrlPrefix(objectTemplateBucket,region);
deleteObjectsWithKeys(urls.stream().filter(url->url.startsWith(domainPrefix)).map(url->url.replace(domainPrefix,"")).collect(Collectors.toList()));
}
/**
* 从当前存储桶复制对象到目标存储桶,存储桶无需填写 APPId,支持目标跨域拷贝
*
* @param sourceKey 原对象key
* @param targetRegion 目标地域
* @param targetBucketName 目标存储桶
* @param targetKey 目标对象key
* @return 复制后的对象的url
*/
@Override
public String copyObject(String sourceKey, String targetRegion, String targetBucketName, String targetKey)
{
throw new UnsupportedOperationException("can not copy file with base template");
}
/**
* 关闭cos客户端连接
*/
@Override
public void close()
{
cosClient.shutdown();
}
/**
*
* 创建拷贝专用TransferManager
*
* @param targetRegion 目标地域
* @return TransferManager
*/
protected TransferManager newCopyTransferManager(String targetRegion)
{
TransferManager transferManager = copyTransferManagerMap.get(targetRegion);
if(transferManager != null)
{
return transferManager;
}
else
{
copyTransferManagerMap.put
(targetRegion, (transferManager = new TransferManager(new COSClient(cosClientProperties.getCosCredentials(),new ClientConfig(new Region(targetRegion))))));
return transferManager;
}
}
/**
* 创建复制请求
* @param sourceKey 源对象的key
* @param targetBucketName 目标bucket name
* @param targetKey 目标key
* @return CopyObjectRequest
*/
protected CopyObjectRequest newCopyObjectRequest(String sourceKey,String targetBucketName,String targetKey)
{
return new CopyObjectRequest(new Region(region),
objectTemplateBucket,
sourceKey,
targetBucketName,
targetKey);
}
//返回原cos client
protected COSClient newCopySourceCOSClient()
{
return cosClient;
}
/**
* 获取腾讯云标准的存储桶名
* @param bucketName 存储桶名
* @return 标准存储桶名
*/
protected String getStandardBucketName(String bucketName)
{
return COSUtil.getTencloudStandardBucketName(bucketName,cosClientProperties.getAppId());
}
/**
* 根据对象键生成对象url
* @param objectKey 对象键
* @return 对象url
*/
protected String getObjectUrl(String objectKey)
{
return COSUtil.getTencloudObjectUrl(objectTemplateBucket,region,objectKey);
}
/**
* 设置操作模板的存储桶,无需填写APP ID
* @param objectTemplateBucket 操作的存储桶
*/
public void setObjectTemplateBucket(String objectTemplateBucket)
{
COSUtil.assertObjectNull(objectTemplateBucket);
this.objectTemplateBucket = getStandardBucketName(objectTemplateBucket);
}
/**
*
* 获取操作模板的存储桶
*
* @return 操作的存储桶
*/
public String getObjectTemplateBucket()
{
return objectTemplateBucket;
}
/**
* 获取上传对象的大小限制
* @return 上传对象的大小限制
*/
public int getUploadLimitSize()
{
return cosClientProperties.getUploadLimitSize();
}
/**
* 获取当前模板的region
* @return 地域
*/
public String getRegion()
{
return region;
}
public void setRegion(String region)
{
COSUtil.assertObjectNull(region);
this.region = region;
}
}