一、需求背景
1、oss文件系統是阿里的存儲文件的服務。
2、以往一個項目中文件可能存放在多個oss上,也就會有多份配置,造成冗餘和維護困難。
3、爲了oss配置能夠統一維護,可以將其存放到數據庫表中,調用時根據指定的token加載對應的配置進行操作。
4、爲了高效的工作,在第一次調用時將配置加載到內存中。爲了在數據庫更新時及時更新內存,使用觀察者進行設置。
二、概要設計
1、類結構
2、數據庫er圖(關鍵字段)
三、詳細設計
1、OssServicce*****Impl類
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import common.utils.AES;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.Bucket;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
/**
* oss 文件創建,刪除,讀取,訪問url 的實現類
*
*
*/
public class OssService****Impl implements OssService*** {
private Logger logger = LoggerFactory.getLogger(OssServiceFacadeImpl.class);
// 默認的BucketName
private String defaultBucketName;
// 配置的bucket的文件夾名
private String defaultFilePath;
// 是否encode true, false
private boolean encode = false;
// 採用的是AES加密
private String encodeKey;
// oss下載的url
private String ossFileHttpUrl;
// oss的key
private String ossKey;
// oss的上secret
private String ossSecret;
// 上傳單個文件最大大小,默認200M
private long fileMaxSize = 200 * 1024 * 1024L;
// oss的endpoint
private String endpoint;
protected static Map<String, String> contentType = new HashMap<String, String>();
// 上傳文件的時候是否默認需要先檢查bucket是否配置了,默認要檢查,上線前建議先去oss上新建bucket,採用不檢查bucket效率更好
private boolean checkBucket = true;
private boolean formatRequired = false;
// 是否encode true, false
private boolean cacheControl = false;
// 採用的是AES加密
private String cacheControlRule;
static {
contentType.put("doc", "application/msword");
contentType.put("docx", "application/msword");
contentType.put("ppt", "application/x-ppt");
contentType.put("pptx", "application/x-ppt");
contentType.put("pdf", "application/pdf");
contentType.put("xls", "text/xml");
contentType.put("xlsx", "text/xml");
contentType.put("html", "text/html");
}
/**
* 上傳文件的時候生成oss的文件key,唯一標示一個文件
*
* @return
*/
private String generateFileId() {
return UUID.randomUUID().toString();
}
/**
* 獲取oss client
*
* @return
* @throws Exception
*/
protected OSSClient getOssClient() throws Exception {
if (StringUtils.isBlank(ossKey) || StringUtils.isBlank(ossSecret)) {
logger.error("oss key and oss secret must be configed for OssFileHandleServiceImpl class.");
throw new Exception("oss key and oss secret must be configed for OssFileHandleServiceImpl class.");
}
try {
OSSClient client = null;
if (StringUtils.isBlank(endpoint)) {
client = new OSSClient(ossKey, ossSecret);
} else {
client = new OSSClient(endpoint, ossKey, ossSecret);
}
return client;
} catch (Exception e) {
logger.error(e.getMessage());
throw e;
}
}
/**
* 獲取 bucket
*
* @param client
* @param bucketName
* @return
* @throws Exception
*/
protected Bucket createBucket(OSSClient client, String bucketName) throws Exception {
if (client == null) {
logger.error("oss key and oss secret error.");
throw new Exception("oss key and oss secret error.");
}
boolean exists = client.doesBucketExist(bucketName);
if (exists) {
List<Bucket> buckets = client.listBuckets();
// 遍歷Bucket
for (Bucket bucket : buckets) {
if (bucketName.equals(bucket.getName())) {
return bucket;
}
}
return null;
} else {
Bucket bucket = client.createBucket(bucketName);
return bucket;
}
}
/**
* use default bucketName
*/
@Override
public HashMap<String, Object> createFile(String fileName, String suffix, InputStream input, long fileSize)
throws Exception {
return createFile(defaultBucketName, fileName, suffix, input, fileSize);
}
@Override
public HashMap<String, Object> createFile(String ossFileId,String bucketName, String filePath, String fileName, String suffix, InputStream input,
long fileSize) throws Exception {
InputStream encodeIs = null;
try {
if (StringUtils.isBlank(bucketName)) {
logger.error("bucketName must be configed for OssFileHandleServiceImpl class.");
throw new Exception("bucketName must be configed for OssFileHandleServiceImpl class.");
}
if (fileSize > fileMaxSize) {
logger.error("file Size must be smaller than max file size {}.", fileMaxSize);
throw new Exception("file Size must be smaller than max file size " + fileMaxSize);
}
// 獲取oss client
OSSClient client = getOssClient();
// 如果需要檢查bucket則調用此代碼,一般情況下都不需要檢查,直接在OSS控制檯又管理員新建bucket
if (checkBucket) {
// 判斷bucket是否存在,不存在則創建bucket
boolean exists = client.doesBucketExist(bucketName);
// 如果不存在則創建bucket
if (!exists) {
Bucket bucket = createBucket(client, bucketName);
if (bucket == null) {
logger.error("Create bucket failed, bucket name is {}", bucketName);
throw new Exception("Create bucket failed, bucket name is " + bucketName);
}
}
}
// 獲取指定文件的輸入流
// 創建上傳Object的Metadata
ObjectMetadata meta = new ObjectMetadata();
String format = "";
// 如果對文件格式有要求,上傳文件時在HEADER中加入格式信息
if (formatRequired) {
int index = fileName.lastIndexOf(".");
if (index != -1) {
format = fileName.substring(index + 1, fileName.length());
format = format.toLowerCase();
if (contentType.containsKey(format)) {
meta.setContentType(contentType.get(format));
}
}
} else {
meta.addUserMetadata("filename", fileName);
meta.addUserMetadata("filesuffix", suffix);
meta.setHeader("x-oss-server-side-encryption", "AES256");
}
//對文件設置緩存策略
if (cacheControl&&!StringUtils.isBlank(cacheControlRule)) {
meta.setCacheControl(cacheControlRule);
}
if(StringUtils.isBlank(ossFileId)){
// 文件的key, 用uuid生成
ossFileId = "";
if (formatRequired) {
ossFileId = generateFileId() + "." + format;
} else {
ossFileId = generateFileId();
}
}else{
//使用用戶自定義的文件key
if (formatRequired) {
ossFileId = ossFileId + "." + format;
}
}
if (!encode) {
encodeIs = input;
// 必須設置ContentLength
meta.setContentLength(fileSize);
} else {
encodeIs = handleEncodeStream(input);
// 必須設置ContentLength
meta.setContentLength(getInputLength(fileSize));
}
// 如果文件放在defaultFilePath這個文件夾下面,則這樣處理
String resourceId = ossFileId;
if(!StringUtils.isBlank(filePath)){
resourceId = filePath + "/" + resourceId;
}
else{
if (!StringUtils.isBlank(defaultFilePath)) {
resourceId = defaultFilePath + "/" + resourceId;
}
}
// 上傳Object.
PutObjectResult result = client.putObject(bucketName, resourceId, encodeIs, meta);
if (result != null && !StringUtils.isBlank(result.getETag())) {
HashMap<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("size", meta.getContentLength());
resultMap.put("ossFileId", ossFileId);
return resultMap;
}
logger.error("Create file error, filename is {}, and file suffix is {}", new Object[] { fileName, suffix });
throw new Exception("Create file error, filename is " + fileName + ", and file suffix is " + suffix);
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
logger.error(e.getMessage());
}
}
if (encodeIs != null) {
try {
encodeIs.close();
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}
}
/**
* 獲得加密後流的長度,算法是 (原流大小/16)*16+16
*
* @param fileSize
* @return
* @throws Exception
*/
protected long getInputLength(long fileSize) throws Exception {
return (fileSize / 16) * 16 + 16;
}
/**
* 加密InputStream,如果encode=true就加密,否則不加密
*
* @param input
* @return
* @throws Exception
*/
protected InputStream handleEncodeStream(InputStream input) throws Exception {
if (encode) {
if (StringUtils.isBlank(encodeKey)) {
throw new Exception(
"encodeKey must be configed for OssFileHandleServiceImpl class if you config true for encode property.");
}
return AES.encodeStream(input, encodeKey);
}
return input;
}
/**
* 解密InputStream,如果encode=true就加密,否則不解密
*
* @param input
* @return
* @throws Exception
*/
protected InputStream handleDecodeStream(InputStream input) throws Exception {
if (encode) {
if (StringUtils.isBlank(encodeKey)) {
throw new Exception(
"encodeKey must be configed for OssFileHandleServiceImpl class if you config true for encode property.");
}
return AES.decodeStream(input, encodeKey);
}
return input;
}
@Override
public boolean delete(String ossFileId) throws Exception {
// 如果文件放在defaultFilePath這個文件夾下面,則這樣處理
if (!StringUtils.isBlank(defaultFilePath)) {
ossFileId = defaultFilePath + "/" + ossFileId;
}
return delete(defaultBucketName, ossFileId);
}
@Override
public boolean delete(String bucketName, String ossFileId) throws Exception {
// 獲取oss client
OSSClient client = getOssClient();
client.deleteObject(bucketName, ossFileId);
return true;
}
@Override
public boolean delete(String filePath, String ossFileId, String format) throws Exception {
// 獲取oss client
OSSClient client = getOssClient();
if (StringUtils.isBlank(filePath)) {
logger.error("刪除OSS附件,filePath不能爲空");
throw new Exception("filePath不能爲空");
}
if (StringUtils.isBlank(format)) {
ossFileId = filePath+"/"+ossFileId;
}
else{
ossFileId = filePath+"/"+ossFileId+"."+format;
}
client.deleteObject(defaultBucketName, ossFileId);
return true;
}
@Override
public InputStream readFile(String ossFileId) throws Exception {
// 如果文件放在defaultFilePath這個文件夾下面,則這樣處理
if (!StringUtils.isBlank(defaultFilePath)) {
ossFileId = defaultFilePath + "/" + ossFileId;
}
return readFile(defaultBucketName, ossFileId);
}
@Override
public InputStream readFile(String bucketName, String ossFileId) throws Exception {
if (StringUtils.isBlank(bucketName)) {
logger.error("bucketName must be configed for OssFileHandleServiceImpl class.");
throw new Exception("bucketName must be configed for OssFileHandleServiceImpl class.");
}
// 獲取oss client
OSSClient client = getOssClient();
InputStream objectContent = null;
// 獲取Object,返回結果爲OSSObject對象
OSSObject object = client.getObject(bucketName, ossFileId);
// 獲取Object的輸入流
objectContent = object.getObjectContent();
if (encode) {
return handleDecodeStream(objectContent);
} else {
return objectContent;
}
}
@Override
public String getUrl(String ossFileId) {
if (StringUtils.isBlank(this.ossFileHttpUrl)) {
return "";
}
return this.ossFileHttpUrl + "?resourceId=" + ossFileId;
}
@Override
public String getUrl(String bucketName, String ossFileId) {
if (StringUtils.isBlank(this.ossFileHttpUrl)) {
return "";
}
return this.ossFileHttpUrl + "?resourceId=" + ossFileId + "&bucketName=" + bucketName;
}
@Override
public ObjectMetadata getFileMetadata(String ossFileId) throws Exception {
if (!StringUtils.isBlank(defaultFilePath)) {
ossFileId = defaultFilePath + "/" + ossFileId;
}
return getFileMetadata(defaultBucketName, ossFileId);
}
@Override
public ObjectMetadata getFileMetadata(String bucketName, String ossFileId) throws Exception {
if (StringUtils.isBlank(bucketName)) {
logger.error("bucketName must be configed for OssFileHandleServiceImpl class.");
throw new Exception("bucketName must be configed for OssFileHandleServiceImpl class.");
}
// 獲取oss client
OSSClient client = getOssClient();
// 獲取Object,返回結果爲OSSObject對象
OSSObject object = client.getObject(bucketName, ossFileId);
// 返回文件屬性對象
return object.getObjectMetadata();
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public boolean isCheckBucket() {
return checkBucket;
}
public void setCheckBucket(boolean checkBucket) {
this.checkBucket = checkBucket;
}
@Override
public HashMap<String, Object> createFile(String bucketName, String fileName, String suffix,
InputStream input, long fileSize) throws Exception {
return this.createFile(null,bucketName, null, fileName, suffix, input, fileSize);
}
@Override
public HashMap<String, Object> createFileByUserDefinedOssFileIdAndFilePath(String ossFileId,String filePath, String fileName, String suffix,
InputStream input, long fileSize) throws Exception {
return this.createFile(ossFileId,defaultBucketName, filePath, fileName, suffix, input, fileSize);
}
@Override
public long getFileSize(String ossFileId) {
long size = 0;
InputStream inputStream = null;
try {
inputStream = readFile(ossFileId);
byte[] buf = new byte[1024];
long len;
while ((len = inputStream.read(buf)) != -1) {
size += len;
}
} catch (Exception e) {
return 0;
} finally {
IOUtils.closeQuietly(inputStream);
}
return size;
}
public boolean isFormatRequired() {
return formatRequired;
}
public void setFormatRequired(boolean formatRequired) {
this.formatRequired = formatRequired;
}
public boolean isCacheControl() {
return cacheControl;
}
public void setCacheControl(boolean cacheControl) {
this.cacheControl = cacheControl;
}
public String getCacheControlRule() {
return cacheControlRule;
}
public void setCacheControlRule(String cacheControlRule) {
this.cacheControlRule = cacheControlRule;
}
2、Configurable****Handler類
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.Bucket;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
/**
* 封裝OSS路由
* 注意:當前類暫不考慮清理緩存操作,也就是說清理緩存需要重啓服務
* @author wb-zcf274530
*
*/
@Component
public class Configurable*****Handler{
private Logger logger = LoggerFactory.getLogger(ConfigurableOssHandler.class);
//業務代碼&配置
private static final Map<String,OssConfigDTO> ossConfigMap = new ConcurrentHashMap<String,OssConfigDTO>();
//業務代碼&連接
//private static final Map<String,OSSClient> ossClientMap = new ConcurrentHashMap<String,OSSClient>();
//服務處理對象
private static final Map<String,OssServiceExtend> ossServiceMap = new ConcurrentHashMap<String,OssServiceExtend>();
@Autowired
private OssConfigService ossConfigService;
/**
* 從數據庫獲取配置信息
* @param businessCode
* @return 失敗返回null
*/
private OssConfigDTO getOssConfigFromDB(String businessCode) {
OssConfigDTO ossConfig = null;
try {
validateNull(businessCode,null);
ActionResult<OssConfigDTO> result = ossConfigService.getOssConfigByBusinessCode(businessCode);
if(result.isSuccess()&&null!=result.getContent()) {
ossConfig = result.getContent();
}
}catch(Exception e) {
throw new AntisPaasException("get ossConfig from db fail,with businessCode:"+businessCode,e);
}
return ossConfig;
}
/**
* 獲取Oss配置信息
* @param businessCode
* @return
*/
public OssConfigDTO getOssConfig(String businessCode){
try {
validateNull(businessCode,null);
OssConfigDTO ossConfig = null;
if(ossConfigMap.containsKey(businessCode)){
ossConfig = ossConfigMap.get(businessCode);
return ossConfig;
}else{
ossConfig = getOssConfigFromDB(businessCode);
if(null==ossConfig){
throw new AntisPaasException("can not find record,with businessCode:"+businessCode);
}else {
ossConfigMap.put(businessCode,ossConfig);
return ossConfig;
}
}
}catch(AntisPaasException e){
logger.warn("get Config by businessCode fail,with businessCode:"+businessCode,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("get Config by businessCode fail,with businessCode:"+businessCode,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取oss配置失敗!",e);
}
}
private OssServiceExtend getOssService(String businessCode) {
if(ossServiceMap.containsKey(businessCode)) {
return ossServiceMap.get(businessCode);
}else {
ossServiceMap.put(businessCode, new OssServiceExtend(businessCode));
}
return ossServiceMap.get(businessCode);
}
/**
*
* @Description:OSS操作服務
* @Author wb-zcf274530 2017/12/15 20:15
*/
private class OssServiceExtend extends EnhanceOssFacadeImpl{
//默認OSS上傳最大文件,200M
public static final long MAX_FILE_SIZE = 200 * 1024 * 1024L;
//業務代碼&連接
public final ThreadLocal<OSSClient> ossClientMap = new ThreadLocal<OSSClient>();
private String businessCode;
public OssServiceExtend(String businessCode) {
init(businessCode);
this.businessCode = businessCode;
}
private void init(String businessCode){
validateNull(businessCode,null);
OssConfigDTO ossConfig = null;
if(ossConfigMap.containsKey(businessCode)){
ossConfig = ossConfigMap.get(businessCode);
}else {
ossConfig = getOssConfigFromDB(businessCode);
if (null == ossConfig) {
throw new AntisPaasException("records do not exist,with businessCode:"+businessCode);
} else {
ossConfigMap.put(businessCode, ossConfig);
}
}
initParentAttribute(ossConfig);
}
/**
* 獲取oss client
*
* @return
* @throws Exception
*/
@Override
protected OSSClient getOssClient() throws Exception {
if (StringUtils.isBlank(this.getOssKey()) || StringUtils.isBlank(this.getOssSecret())) {
throw new AntisPaasException("oss key and oss secret must be configed for OssFileHandleServiceImpl class.");
}
try {
if(ossClientMap.get()!=null) {
return ossClientMap.get();
}
OSSClient client = null;
if (StringUtils.isBlank(this.getEndpoint())) {
client = new OSSClient(this.getOssKey(), this.getOssSecret());
} else {
client = new OSSClient(this.getEndpoint(), this.getOssKey(), this.getOssSecret());
}
if(null==client) {
throw new AntisPaasException("init client fail,with businessCode :"+businessCode);
}
ossClientMap.set(client);
return client;
} catch (Exception e) {
logger.error("get OssClient fail,with this:"+JSONObject.toJSONString(this),e);
throw new AntisPaasException("get OssClient fail,with this:"+JSONObject.toJSONString(this),e);
}
}
public HashMap<String, Object> createFile(String bucketName, String fileName, String suffix, InputStream input, long fileSize) throws Exception {
return this.createFile(null,bucketName, null, fileName, suffix, input, fileSize);
}
public HashMap<String, Object> createFileByUserDefinedOssFileIdAndFilePath(String ossFileId, String filePath, String fileName, String suffix, InputStream input, long fileSize) throws Exception {
return this.createFile(ossFileId,this.getDefaultBucketName(), filePath, fileName, suffix, input, fileSize);
}
public HashMap<String, Object> createFile(String ossFileId,String bucketName, String filePath, String fileName, String suffix, InputStream input,
long fileSize) throws Exception {
InputStream encodeIs = null;
try {
validateNull(bucketName,"域名不能爲空!");
validateTrue(fileSize > this.getFileMaxSize(),"文件大小超過限制,默認200M,當前: " + this.getFileMaxSize());
validateTrue(useRealName&&StringUtils.isBlank(fileName),"文件名不能爲空!");
// 獲取oss client
OSSClient client = getOssClient();
// 如果需要檢查bucket則調用此代碼,一般情況下都不需要檢查,直接在OSS控制檯又管理員新建bucket
checkAndaddBucket(this.isCheckBucket(),client,bucketName);
// 獲取指定文件的輸入流
// 創建上傳Object的Metadata
ObjectMetadata meta = new ObjectMetadata();
String format = "";
// 如果對文件格式有要求,上傳文件時在HEADER中加入格式信息
if (this.isFormatRequired()) {
int index = fileName.lastIndexOf(".");
if (index != -1) {
format = fileName.substring(index + 1, fileName.length());
format = format.toLowerCase();
if (contentType.containsKey(format)) {
meta.setContentType(contentType.get(format));
}
}
} else {
meta.addUserMetadata("filename", fileName);
meta.addUserMetadata("filesuffix", suffix);
meta.setHeader("x-oss-server-side-encryption", "AES256");
}
//對文件設置緩存策略
if (this.isCacheControl()&&!StringUtils.isBlank(this.getCacheControlRule())) {
meta.setCacheControl(this.getCacheControlRule());
}
//設置文件名策略
if(getUseRealName()){
ossFileId = fileName;
}else if(StringUtils.isBlank(ossFileId)){
// 文件的key, 用uuid生成
ossFileId = "";
if (this.isFormatRequired()) {
ossFileId = UUID.randomUUID().toString() + "." + format;
} else {
ossFileId = UUID.randomUUID().toString();
}
}else{
//使用用戶自定義的文件key
if (this.isFormatRequired()) {
ossFileId = ossFileId + "." + format;
}
}
//設置加密
if (!this.isEncode()) {
encodeIs = input;
// 必須設置ContentLength
meta.setContentLength(fileSize);
} else {
encodeIs = handleEncodeStream(input);
// 必須設置ContentLength
meta.setContentLength(getInputLength(fileSize));
}
// 如果文件放在defaultFilePath這個文件夾下面,則這樣處理
String resourceId = ossFileId;
if(!StringUtils.isBlank(filePath)){
resourceId = filePath + "/" + resourceId;
}else{
if (!StringUtils.isBlank(this.getDefaultFilePath())) {
resourceId = this.getDefaultFilePath() + "/" + resourceId;
}
}
// 上傳Object.
PutObjectResult result = client.putObject(bucketName, resourceId, encodeIs, meta);
if (result != null && !StringUtils.isBlank(result.getETag())) {
HashMap<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("size", meta.getContentLength());
resultMap.put("ossFileId", ossFileId);
return resultMap;
}
throw new AntisPaasException("Create file to oss fail!");
}catch(Exception e) {
cleanCache(this.businessCode);
logger.error("Create file error,with ossFileId:{},bucketName:{},filePath:{},fileName:{},suffix:{},fileSize:{}",ossFileId,bucketName,filePath,fileName,suffix,fileSize,e);
throw e;
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}
if (encodeIs != null) {
try {
encodeIs.close();
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}
}
}
public HashMap<String, Object> createFile(String fileName, String suffix, InputStream input, long fileSize)
throws Exception {
return createFile(this.getDefaultBucketName(), fileName, suffix, input, fileSize);
}
@Override
public boolean delete(String bucketName, String ossFileId) throws Exception {
// 構造oss Client
OSSClient client = getOssClient();
client.deleteObject(bucketName, ossFileId);
return true;
}
@Override
public InputStream readFile(String bucketName, String ossFileId) throws Exception {
if (StringUtils.isBlank(bucketName)) {
logger.warn("bucketName must be configed for OssFileHandleServiceImpl class.");
throw new AntisPaasException("bucketName must be configed for OssFileHandleServiceImpl class.");
}
// 構造oss client
OSSClient client = getOssClient();
InputStream objectContent = null;
// 獲取對象
OSSObject object = client.getObject(bucketName, ossFileId);
// 返回
objectContent = object.getObjectContent();
if (this.isEncode()) {
return handleDecodeStream(objectContent);
} else {
return objectContent;
}
}
@Override
public ObjectMetadata getFileMetadata(String bucketName, String ossFileId) throws Exception {
if (StringUtils.isBlank(bucketName)) {
logger.warn("bucketName must be configed for OssFileHandleServiceImpl class.");
throw new AntisPaasException("bucketName must be configed for OssFileHandleServiceImpl class.");
}
// 構造oss client
OSSClient client = getOssClient();
// 獲取對象
OSSObject object = client.getObject(bucketName, ossFileId);
// 返回
return object.getObjectMetadata();
}
private void checkAndaddBucket(boolean isNeed,OSSClient client,String bucketName) throws Exception {
if(isNeed) {
// 判斷bucket是否存在,不存在則創建bucket
boolean exists = client.doesBucketExist(bucketName);
// 如果不存在則創建bucket
if (!exists) {
Bucket bucket = createBucket(client, bucketName);
if (bucket == null) {
throw new AntisPaasException("Create bucket failed, with bucket name is " + bucketName);
}
}
}
}
/**
* 獲取 bucket
*
* @param client
* @param bucketName
* @return
* @throws Exception
*/
protected Bucket createBucket(OSSClient client, String bucketName) throws Exception {
if (client == null) {
logger.warn("oss key and oss secret error.");
throw new AntisPaasException("oss key and oss secret error.");
}
boolean exists = client.doesBucketExist(bucketName);
if (exists) {
List<Bucket> buckets = client.listBuckets();
// 遍歷Bucket
for (Bucket bucket : buckets) {
if (bucketName.equals(bucket.getName())) {
return bucket;
}
}
return null;
} else {
Bucket bucket = client.createBucket(bucketName);
return bucket;
}
}
/**
* 初始化父類屬性
*/
private void initParentAttribute(OssConfigDTO config){
this.setDefaultBucketName(config.getOssBucket());
this.setDefaultFilePath(config.getDefaultPath());
this.setEncodeKey(config.getEncryptKey());
this.setEndpoint(config.getOssEndpoint());
this.setOssFileHttpUrl(config.getFileHttpUrl());
this.setOssKey(config.getOssKey());
this.setOssSecret(config.getOssSecret());
this.setCacheControlRule(config.getCacheControlRule());
this.setCheckBucket(config.getCheckBucket());
this.setEncode(config.getEncode());
this.setFormatRequired(config.getFormatRequired());
this.setUseRealName(config.getUseRealName());
this.setCacheControl(config.getCacheControl());
//默認200M
if(null==config.getFileMaxSize()) {
this.setFileMaxSize(MAX_FILE_SIZE);
}else {
this.setFileMaxSize(config.getFileMaxSize());
}
}
}
/**
* 創建文件流對象
* @param businessCode
* @param fileName
* @param suffix
* @param input
* @param fileSize
* @return
* @throws Exception
*/
public HashMap<String, Object> createFile(String businessCode, String fileName, String suffix, InputStream input, long fileSize) throws Exception{
try {
validateNull(businessCode,null);
validateNull(input,null);
return getOssService(businessCode).createFile(fileName, suffix, input, fileSize);
}catch(AntisPaasException e) {
logger.warn("createFile fail,with businessCode:{},fileName:{}, suffix:{},fileSize:{}",businessCode,fileName,suffix,fileSize,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("createFile fail,with businessCode:{},fileName:{}, suffix:{},fileSize:{}",businessCode,fileName,suffix,fileSize,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"創建流文件失敗!",e);
}
}
/**
* 創建文件流對對象
* @param businessCode
* @param bucketName
* @param fileName
* @param suffix
* @param input
* @param fileSize
* @return
* @throws Exception
*/
public HashMap<String, Object> createFile(String businessCode, String bucketName, String fileName,
String suffix, InputStream input, long fileSize) throws Exception{
try {
validateNull(businessCode,null);
validateNull(input,null);
return getOssService(businessCode).createFile(bucketName, fileName, suffix, input, fileSize);
}catch(AntisPaasException e) {
logger.warn("createFile fail,with businessCode:{},bucketName:{}, fileName:{}, suffix:{},fileSize:{}",businessCode,bucketName,fileName,suffix,fileSize,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("createFile fail,with businessCode:{},bucketName:{}, fileName:{}, suffix:{},fileSize:{}",businessCode,bucketName,fileName,suffix,fileSize,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取文件流對象失敗!",e);
}
}
/**
* 創建文件流對象
* @param businessCode
* @param ossFileId
* @param filePath
* @param fileName
* @param suffix
* @param input
* @param fileSize
* @return
* @throws Exception
*/
public HashMap<String, Object> createFileByUserDefinedOssFileIdAndFilePath(String businessCode,
String ossFileId, String filePath, String fileName, String suffix, InputStream input, long fileSize) throws Exception{
try {
validateNull(businessCode,null);
validateNull(input,null);
return getOssService(businessCode).createFileByUserDefinedOssFileIdAndFilePath(ossFileId, filePath, fileName, suffix, input, fileSize);
}catch(AntisPaasException e) {
logger.warn("createFile By UserDefined OssFileId And FilePath fail,with businessCode:{},ossFileId:{}, filePath:{}, fileName:{}, suffix:{},fileSize:{}",businessCode,ossFileId, filePath, fileName, suffix,fileSize,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("createFile By UserDefined OssFileId And FilePath fail,with businessCode:{},ossFileId:{}, filePath:{}, fileName:{}, suffix:{},fileSize:{}",businessCode,ossFileId, filePath, fileName, suffix,fileSize,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取文件流對象失敗!",e);
}
}
/**
* 創建文件流對象
* @param businessCode
* @param ossFileId
* @param bucketName
* @param filePath
* @param fileName
* @param suffix
* @param input
* @param fileSize
* @return
* @throws Exception
*/
public HashMap<String, Object> createFile(String businessCode, String ossFileId, String bucketName,
String filePath, String fileName, String suffix, InputStream input, long fileSize) throws Exception {
try {
validateNull(businessCode,null);
validateNull(input,null);
return getOssService(businessCode).createFile(ossFileId, bucketName, filePath, fileName, suffix, input, fileSize);
}catch(AntisPaasException e) {
logger.warn("createFile fail,with businessCode:{},ossFileId:{}, bucketName:{},filePath:{}, fileName:{}, suffix:{},fileSize:{}",businessCode,ossFileId,bucketName, filePath, fileName, suffix,fileSize,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("createFile fail,with businessCode:{},ossFileId:{}, bucketName:{},filePath:{}, fileName:{}, suffix:{},fileSize:{}",businessCode,ossFileId,bucketName, filePath, fileName, suffix,fileSize,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"創建文件流對象失敗!",e);
}
}
/**
* 根據指定域名&資源Id獲取文件流對象
* @param businessCode
* @param bucketName
* @param ossFileId
* @return
* @throws Exception
*/
public InputStream readFile(String businessCode, String bucketName, String ossFileId) throws Exception{
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
validateNull(bucketName,null);
return getOssService(businessCode).readFile(bucketName,ossFileId);
}catch(AntisPaasException e) {
logger.warn("readFile fail,with businessCode:{},bucketName:{}, ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("readFile fail,with businessCode:{},bucketName:{}, ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取文件流對象失敗!",e);
}
}
/**
* 根據資源Id獲取文件流對象
* @param businessCode
* @param ossFileId
* @return
* @throws Exception
*/
public InputStream readFile(String businessCode, String ossFileId) throws Exception{
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
return getOssService(businessCode).readFile(ossFileId);
}catch(AntisPaasException e) {
logger.warn("readFile fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("readFile fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取文件流對象失敗!",e);
}
}
/**
* 根據資源Id刪除文件
* @param businessCode
* @param ossFileId
* @return
* @throws Exception
*/
public boolean delete(String businessCode, String ossFileId) throws Exception{
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
return getOssService(businessCode).delete(ossFileId);
}catch(AntisPaasException e) {
logger.warn("delete fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("delete fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"刪除文件失敗!",e);
}
}
/**
* 根據指定域名&資源Id刪除文件
* @param businessCode
* @param bucketName
* @param ossFileId
* @return
* @throws Exception
*/
public boolean delete(String businessCode, String bucketName, String ossFileId) throws Exception{
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
validateNull(bucketName,null);
return getOssService(businessCode).delete(bucketName,ossFileId);
}catch(AntisPaasException e) {
logger.warn("delete fail,with businessCode:{},bucketName:{},ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("delete fail,with businessCode:{},bucketName:{},ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"刪除文件失敗!",e);
}
}
/**
* 根據指定域名&資源Id獲取文件配置信息
* @param businessCode
* @param bucketName
* @param ossFileId
* @return
* @throws Exception
*/
public ObjectMetadata getFileMetadata(String businessCode, String bucketName, String ossFileId) throws Exception{
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
validateNull(bucketName,null);
return getOssService(businessCode).getFileMetadata(bucketName,ossFileId);
}catch(AntisPaasException e) {
logger.warn("getFileMetadata fail,with businessCode:{},bucketName:{}, ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("getFileMetadata fail,with businessCode:{},bucketName:{}, ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取配置信息失敗!",e);
}
}
/**
* 根據資源Id獲取文件配置信息
* @param businessCode
* @param ossFileId
* @return
* @throws Exception
*/
public ObjectMetadata getFileMetadata(String businessCode, String ossFileId) throws Exception{
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
return getOssService(businessCode).getFileMetadata(ossFileId);
}catch(AntisPaasException e) {
logger.warn("getFileMetadata fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("getFileMetadata fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取配置信息失敗!",e);
}
}
/**
* 根據指定域名&資源Id獲取下載路徑
* @param businessCode
* @param bucketName
* @param ossFileId
* @return
*/
public String getUrl(String businessCode, String bucketName, String ossFileId) {
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
validateNull(bucketName,null);
return getOssService(businessCode).getUrl(bucketName,ossFileId);
}catch(AntisPaasException e) {
logger.warn("getUrl fail,with businessCode:{},bucketName:{}, ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("getUrl fail,with businessCode:{},bucketName:{}, ossFileId:{}",businessCode,bucketName,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取下載路徑失敗!",e);
}
}
/**
* 根據資源id獲取文件下載路徑
* @param businessCode
* @param ossFileId
* @return
*/
public String getUrl(String businessCode, String ossFileId) {
try {
validateNull(businessCode,null);
validateNull(ossFileId,null);
return getOssService(businessCode).getUrl(ossFileId);
}catch(AntisPaasException e) {
logger.warn("getUrl fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("getUrl fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取下載路徑失敗!",e);
}
}
/**
* 根據資源Id獲取文件大小
* @return
*/
public long getFileSize(String businessCode,String ossFileId) {
try {
return getOssService(businessCode).getFileSize(ossFileId);
}catch(AntisPaasException e) {
logger.warn("get File Size fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(e.getCode(),e.getMessage(),e);
}catch(Exception e) {
logger.error("get File Size fail,with businessCode:{},ossFileId:{}",businessCode,ossFileId,e);
throw new AntisPaasException(AntisPaasErrorCode.error_0004.getErrorCode(),"獲取文件大小失敗!",e);
}
}
public static void cleanCache(Object businessCode) {
ossServiceMap.remove(businessCode);
ossConfigMap.remove(businessCode);
//ossClientMap.remove(businessCode);
}
public void beginAction(Object businessCode) {
//Don't do any thing
}
private void validateNull(Object input,String errMsg) {
if(null==input) {
if(StringUtils.isNotBlank(errMsg)) {
throw new AntisPaasException(AntisPaasErrorCode.error_0001.getErrorCode(),errMsg);
}else {
throw new AntisPaasException(AntisPaasErrorCode.error_0001.getErrorCode(), AntisPaasErrorCode.error_0001.getErrorMsg());
}
}
}
private void validateTrue(boolean isTrue,String errMsg) {
if(isTrue) {
throw new AntisPaasException(AntisPaasErrorCode.error_0005.getErrorCode(),errMsg);
}
}
/**
* 獲得加密後流的長度,算法是 (原流大小/16)*16+16
*
* @param fileSize
* @return
* @throws Exception
*/
protected long getInputLength(long fileSize) throws Exception {
return (fileSize / 16) * 16 + 16;
}
}
3、觀察者模式很簡單,可以參考觀察者者的具體定義。
關鍵:
1、spring中 implements ApplicationContextAware獲取上下文
2、context.getBeansOfType(MessageSend.class) 上下文中通過接口定義獲取所有觀察者接口的實現類
四、相關maven配置
com.aliyun.oss
aliyun-sdk-oss
2.2.1