oss文件系统路由方案实现

一、需求背景
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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值