• Java项目接入阿里云OSS存储


    需求背景

    目前公司内部项目所支持的文件云存储方式还是公司内部项目组提供的方案,但在时间的考验之下,弊端显现,尤其是灾备切换过程中需要切换访问地址,这种操作不方便,更可能因为中间过程的失误导致资源不可用,而且这种操作也会带来资源可用的延时,仔细斟酌发现这种操作似乎并不合逻辑。

    在众多项目组的千呼万唤之下,阿里云的OSS存储方案进入了我们的视线,依托公共云环境,屏蔽项目本身切换状态可能带来的资源不可用的问题,将资源存储与访问独立出来,极大的与企业自有项目解耦,同时降低企业自身项目运行状态对公共资源访问的影响。

    项目接入

    Captain的本项目基于JDK1.8,采用SpringBoot框架开发。

    前期准备

    从阿里云平台获取到endpoint、accessKeyId、accessKeySecret相关配置信息,因为只有在这些信息的支持下,才能展开后续功能的开发。

    创建bucket(存储命名空间、平台唯一才行),可以在阿里云操作台建立,也可以通过代码生成。

    Maven依赖

    1 <dependency>
    2     <groupId>com.aliyun.oss</groupId>
    3     <artifactId>aliyun-sdk-oss</artifactId>
    4     <version>2.8.3</version>
    5 </dependency>

    属性配置

    可以将和环境相关的固定配置类信息放置于properties文件中:

    # aliyun oss
    aliyun.oss.endpoint="http://oss-cn-hangzhou.aliyuncs.com"
    aliyun.oss.keyid=<yourAccessKeyId>
    aliyun.oss.keysecret=<yourAccessKeySecret>
    aliyun.oss.bucketname=<yourBucketName>
    
    # aliyun filehost based on dev/test/prod(tha/idn)
    aliyun.oss.filehost=dev

    编写工具类

      1 /**
      2  * @Project: captain-supply-chain
      3  * @PackageName: com.captain.supply-chain.common.file
      4  * @Author: Captain&D
      5  * @cnblogs: https://www.cnblogs.com/captainad
      6  * @DateTime: 2019/5/10 18:12.
      7  * @Description: Upload file to Aliyun OSS.
      8  */
      9 @Slf4j
     10 @Component
     11 public class AliyunOssService {
     12 
     13     /**
     14      * 斜杠
     15      */
     16     private final String FLAG_SLANTING_ROD = "/";
     17     /**
     18      * http://
     19      */
     20     private final String FLAG_HTTP = "http://";
     21     /**
     22      * https://
     23      */
     24     private final String FLAG_HTTPS = "https://";
     25     /**
     26      * 空字符串
     27      */
     28     private final String FLAG_EMPTY_STRING = "";
     29     /**
     30      * 点号
     31      */
     32     private final String FLAG_DOT = ".";
     33     /**
     34      * 横杠
     35      */
     36     private final String FLAG_CROSSBAR = "-";
     37 
     38     /**
     39      * 缺省的最大上传文件大小:20M
     40      */
     41     private final int DEFAULT_MAXIMUM_FILE_SIZE = 20;
     42 
     43     /**
     44      * endpoint
     45      */
     46     @Value("${aliyun.oss.endpoint}")
     47     private String endpoint;
     48 
     49     /**
     50      * access key id
     51      */
     52     @Value("${aliyun.oss.keyid}")
     53     private String accessKeyId;
     54 
     55     /**
     56      * access key secret
     57      */
     58     @Value("${aliyun.oss.keysecret}")
     59     private String accessKeySecret;
     60 
     61     /**
     62      * bucket name (namespace)
     63      */
     64     @Value("${aliyun.oss.bucketname}")
     65     private String bucketName;
     66 
     67     /**
     68      * file host (dev/test/prod)
     69      */
     70     @Value("${aliyun.oss.filehost}")
     71     private String fileHost;
     72 
     73     @Autowired
     74     protected GetSetCacheService getSetCacheService;
     75 
     76     /**
     77      * 以文件流的方式上传文件
     78      * @Author: Captain&D
     79      * @cnblogs: https://www.cnblogs.com/captainad
     80      * @param fileName 文件名称
     81      * @param filePath 文件路径
     82      * @param inputStream 文件输入流
     83      * @return
     84      */
     85     public String uploadFile(String fileName, String filePath, InputStream inputStream) {
     86         return coreUpload(fileName, filePath, inputStream);
     87     }
     88 
     89     /**
     90      * 核心上传功能
     91      * @Author: Captain&D
     92      * @cnblogs: https://www.cnblogs.com/captainad
     93      * @param fileName 文件名
     94      * @param filePath 文件路径
     95      * @param inputStream 文件输入流
     96      * @return
     97      */
     98     private String coreUpload(String fileName, String filePath, InputStream inputStream) {
     99         log.info("Start to upload file....");
    100         if(StringUtils.isEmpty(fileName) || inputStream == null) {
    101             log.error("Filename Or inputStream is lack when upload file.");
    102             return null;
    103         }
    104         if(StringUtils.isEmpty(filePath)) {
    105             log.warn("File path is lack when upload file but we automatically generated");
    106             String dateCategory = DateUtil.getFormatDate(new Date(), "yyyyMMdd");
    107             filePath = FLAG_SLANTING_ROD.concat(dateCategory).concat(FLAG_SLANTING_ROD);
    108         }
    109         String fileUrl;
    110         OSSClient ossClient = null;
    111         try{
    112 
    113             // If the upload file size exceeds the limit
    114             long maxSizeAllowed = getMaximumFileSizeAllowed();
    115             if(Long.valueOf(inputStream.available()) > maxSizeAllowed) {
    116                 log.error("Uploaded file is too big.");
    117                 return null;
    118             }
    119 
    120             // Create OSS instance
    121             ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
    122 
    123             // Create bucket if not exists
    124             if (!ossClient.doesBucketExist(bucketName)) {
    125                 log.info("Bucket '{}' is not exists and create it now.", bucketName);
    126                 ossClient.createBucket(bucketName);
    127                 CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
    128                 createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
    129                 ossClient.createBucket(createBucketRequest);
    130             }
    131 
    132             /*********************************/
    133             // List the bucket in my account
    134             //listBuckets(ossClient);
    135             /*********************************/
    136 
    137             // File path format
    138             if(!filePath.startsWith(FLAG_SLANTING_ROD)) {
    139                 filePath = FLAG_SLANTING_ROD.concat(filePath);
    140             }
    141             if(!filePath.endsWith(FLAG_SLANTING_ROD)) {
    142                 filePath = filePath.concat(FLAG_SLANTING_ROD);
    143             }
    144 
    145             // File url
    146             StringBuilder buffer = new StringBuilder();
    147             buffer.append(fileHost).append(filePath).append(fileName);
    148             fileUrl = buffer.toString();
    149             log.info("After format the file url is {}", fileUrl);
    150 
    151             // Upload file and set ACL
    152             PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, inputStream));
    153             ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
    154             if(result != null) {
    155                 log.info("Upload result:{}", result.getETag());
    156                 log.info("Upload file {} successfully.", fileName);
    157             }
    158             fileUrl = getHostUrl().concat(fileUrl);
    159             log.info("Call path is {}", fileUrl);
    160 
    161             /***********************************/
    162             // List objects in your bucket
    163             //listObjects(ossClient);
    164             /***********************************/
    165 
    166         }catch (Exception e){
    167             log.error("Upload file failed.", e);
    168             fileUrl = null;
    169         }finally {
    170             if(ossClient != null) {
    171                 ossClient.shutdown();
    172             }
    173         }
    174         return fileUrl;
    175     }
    176 
    177     /**
    178      * 列出buckets下的所有文件
    179      * @Author: Captain&D
    180      * @cnblogs: https://www.cnblogs.com/captainad
    181      * @param ossClient
    182      */
    183     private void listObjects(OSSClient ossClient) {
    184         System.out.println("Listing objects");
    185         ObjectListing objectListing = ossClient.listObjects(bucketName);
    186         for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
    187             System.out.println(" - " + objectSummary.getKey() + "  " +
    188                     "(size = " + objectSummary.getSize() + ")");
    189         }
    190         System.out.println();
    191     }
    192 
    193     /**
    194      * 列出当前用户下的所有bucket
    195      * @Author: Captain&D
    196      * @cnblogs: https://www.cnblogs.com/captainad
    197      * @param ossClient
    198      */
    199     private void listBuckets(OSSClient ossClient) {
    200         System.out.println("Listing buckets");
    201         ListBucketsRequest listBucketsRequest = new ListBucketsRequest();
    202         listBucketsRequest.setMaxKeys(500);
    203         for (Bucket bucket : ossClient.listBuckets()) {
    204             System.out.println(" - " + bucket.getName());
    205         }
    206         System.out.println();
    207     }
    208 
    209     /**
    210      * 以文件的形式上传文件
    211      * @Author: Captain&D
    212      * @cnblogs: https://www.cnblogs.com/captainad
    213      * @param fileName
    214      * @param filePath
    215      * @param file
    216      * @return
    217      */
    218     public String uploadFile(String fileName, String filePath, File file) {
    219         if(file == null) {
    220             log.warn("File is lack when upload.");
    221             return null;
    222         }
    223         if(StringUtils.isEmpty(fileName)) {
    224             log.warn("File name is lack when upload file but we automatically generated");
    225             String uuidFileName = UUID.randomUUID().toString().replace(FLAG_CROSSBAR, FLAG_EMPTY_STRING);
    226             String fname = file.getName();
    227             String suffix = fname.substring(fname.lastIndexOf(FLAG_DOT), fname.length());
    228             fileName = uuidFileName.concat(suffix);
    229         }
    230         InputStream inputStream = null;
    231         String fileUrl = null;
    232         try{
    233             inputStream = new FileInputStream(file);
    234             fileUrl = uploadFile(fileName, filePath, inputStream);
    235         }catch (Exception e){
    236             log.error("Upload file error.", e);
    237         }finally {
    238             IOUtils.safeClose(inputStream);
    239         }
    240         return fileUrl;
    241     }
    242 
    243     /**
    244      * 获取访问的base地址
    245      * @Author: Captain&D
    246      * @cnblogs: https://www.cnblogs.com/captainad
    247      * @return
    248      */
    249     private String getHostUrl() {
    250         String hostUrl = null;
    251         if(this.endpoint.startsWith(FLAG_HTTP)) {
    252             hostUrl = FLAG_HTTP.concat(this.bucketName).concat(FLAG_DOT)
    253                     .concat(this.endpoint.replace(FLAG_HTTP, FLAG_EMPTY_STRING)).concat(FLAG_SLANTING_ROD);
    254         } else if (this.endpoint.startsWith(FLAG_HTTPS)) {
    255             return FLAG_HTTPS.concat(this.bucketName).concat(FLAG_DOT)
    256                     .concat(this.endpoint.replace(FLAG_HTTPS, FLAG_EMPTY_STRING)).concat(FLAG_SLANTING_ROD);
    257         }
    258         return hostUrl;
    259     }
    260 
    261     /**
    262      * 获取最大允许上传文件的大小
    263      * @Author: Captain&D
    264      * @cnblogs: https://www.cnblogs.com/captainad
    265      * @return
    266      */
    267     private long getMaximumFileSizeAllowed() {
    268         // 缓存单位是M
    269         String maxConfigVal = getSetCacheService.getConfigValue("upload_maximum_file_size");
    270         if(StringUtils.isEmpty(maxConfigVal)) {
    271             return DEFAULT_MAXIMUM_FILE_SIZE * 1024L * 1024L;
    272         }else {
    273             return Long.valueOf(maxConfigVal.trim()) * 1024L * 1024L;
    274         }
    275     }
    276 
    277     /**
    278      * 删除文件
    279      * @Author: Captain&D
    280      * @cnblogs: https://www.cnblogs.com/captainad
    281      * @param fileUrl 文件访问的全路径
    282      */
    283     public void deleteFile(String fileUrl) {
    284         log.info("Start to delete file from OSS.{}", fileUrl);
    285         if(StringUtils.isEmpty(fileUrl)
    286                 || (!fileUrl.startsWith(FLAG_HTTP)
    287                 && !fileUrl.startsWith(FLAG_HTTPS))) {
    288             log.error("Delete file failed because the invalid file address. -> {}", fileUrl);
    289             return;
    290         }
    291         OSSClient ossClient = null;
    292         try{
    293             /**
    294              * http:// bucketname                                dev/test/pic/abc.jpg = key
    295              * http:// captainad.oss-ap-southeast-1.aliyuncs.com/dev/test/pic/abc.jpg
    296              */
    297             String key = fileUrl.replace(getHostUrl(), FLAG_EMPTY_STRING);
    298             if(log.isDebugEnabled()) {
    299                 log.debug("Delete file key is {}", key);
    300             }
    301             ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
    302             ossClient.deleteObject(bucketName, key);
    303         }catch (Exception e){
    304            log.error("Delete file error.", e);
    305         } finally {
    306             if(ossClient != null) {
    307                 ossClient.shutdown();
    308             }
    309         }
    310     }
    311 
    312 }

    参考资料

    1、https://help.aliyun.com/document_detail/32008.html

  • 相关阅读:
    Fortran编译器之一GUN Fortran安装(Windows XP)
    c++动态绑定的技术实现
    c++标准库比较
    java array
    java常用的基础容器
    mac sublime text 3 add ctags plugin
    git fetch
    查看远程分支的log
    git删除分支
    detached HEAD state
  • 原文地址:https://www.cnblogs.com/captainad/p/10896380.html
Copyright © 2020-2023  润新知