项目数据直线增长,自建存储服务器存在诸多劣势,选择一个数据稳定、业务可靠的数据存储服务器
OBS基本概念 桶 桶OBS中存储对象的容器。桶中的所有对象都处于同一逻辑层级。每个桶都有自己的访问权限、所属区域等属性,可以在不同区域创建不同访问权限的桶,并配置更多高级属性来满足不同场景的存储诉求。
桶名必须是全局唯一的且不能修改,即用户创建的桶不能与自己已创建的 其他桶名称相同,也不能与其他用户创建的桶名称相同。桶所属的区域在创建后也不能修改。每个桶在创建时都会生成默认的桶ACL(Access Control List,访问控制列 表),桶ACL的每项包含了对被授权用户授予什么样的权限,如读取权限、写入权限 等。用户只有对桶有相应的权限,才可以对桶进行操作,如创建、删除、显示、设置 桶ACL等。
对象 对象是OBS中数据存储的基本单位,一个对象实际是一个文件的数据与其相关属性信息的集合体。用户上传至OBS的数据都以对象的形式保存在桶中。
对象包括了Key,Metadata,Data三部分:
● Key:键值,即对象的名称,一个桶里的每个对象必须拥有唯一的对象键值。
● Metadata:元数据,对象的描述信息,包括系统元数据和用户元数据,这些元数据以键值对(Key-Value)的形式被上传到OBS中,系统元数据由OBS
● Data:数据,即文件的数据内容。
访问密钥(AK/SK) OBS支持通过AK/SK认证方式进行认证鉴权,即使用Access Key ID(AK)/Secret Access Key(SK)加密的方法来验证某个请求发送者身份。当您使用OBS提供的API进行二次开发并通过AK/SK认证方式完成认证鉴权时,需要按照OBS定义的签名算法来计 算签名并s添加到请求中。
● Access Key Id(AK):访问密ID。与私有访问密钥关联的唯一标识符;访问密钥ID和私有访问密钥一起使用,对请求进行加密签名。
● Secret Access Key(SK):与访问密钥ID结合使用的私有访问密钥,对请求进行加密签名,可标识发送方,并防止请求被修改。
终端节点(Endpoint)和访问域名 终端节点(Endpoint):OBS为每个区域提供一个终端节点,终端节点可以理解为OBS在不同区域的区域域名,用于处理各自区域的访问请求。
注:连接OBS时需要访问密钥(AK/SK)以及终端节点(Endpoint)进行认证连接,可查看我提供的代码了解基本格式
开发环境准备 引入JDK依赖 1 2 3 4 5 <dependency > <groupId > com.huaweicloud</groupId > <artifactId > esdk-obs-java</artifactId > <version > 3.22.12</version > </dependency >
因版本问题可能遇到的错误
1 2 3 4 5 6 7 Exception in thread "main" java.lang.NoSuchMethodError: 'okhttp3.RequestBody okhttp3.RequestBody.create(java.lang.String, okhttp3.MediaType)' at com.obs.services.internal.RestConnectionService.createRequestBuilder(RestConnectionService.java:157 ) at com.obs.services.internal.RestConnectionService.setupConnection(RestConnectionService.java:148 ) at com.obs.services.internal.RestConnectionService.setupConnection(RestConnectionService.java:124 ) at com.obs.services.internal.RestStorageService.performRequest(RestStorageService.java:395 ) at com.obs.services.internal.RestStorageService.performRequest(RestStorageService.java:388 )
如果遇到 okhttp 报错问题,报错是因为升级SDK后okhttp使用了老版本的原因,尝试升级okhttp,版本按个人情况修改
1 2 3 4 5 <dependency > <groupId > com.squareup.okhttp3</groupId > <artifactId > okhttp</artifactId > <version > 4.9.3</version > </dependency >
在我默认提供的esdk-obs-java与okhttp3版本使用是正常,如有版本引发的意外问题可交流讨论
对象的上传与下载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 package com.example.demo2dateobs;import com.obs.services.ObsClient;import com.obs.services.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import java.io.*;import java.util.HashMap;import java.util.Map;@Controller @RequestMapping("/test") public class DateObsController { private final static Logger logger = LoggerFactory.getLogger(DateObsController.class); private final static String endPoint = "" ; private final static String ak = "" ; private final static String sk = "" ; @GetMapping("/uploadByte") public boolean uploadFile () { ObsClient obsClient = null ; try { obsClient = new ObsClient (ak, sk, endPoint); String content = "Hello OBS" ; HeaderResponse response = obsClient.putObject("bucketName" ,"objectKey" ,new ByteArrayInputStream (content.getBytes())); int statusCode = response.getStatusCode(); if (200 == statusCode) { return true ; } obsClient.close(); } catch (IOException e) { logger.info("文件上传失败:{}" , e.getMessage(), e); } return false ; } @GetMapping("/uploadFile") public boolean uploadFileByte () { ObsClient obsClient = null ; try { obsClient = new ObsClient (ak, sk, endPoint); File file = new File ("File Path" ); FileInputStream fileStream = new FileInputStream (file); HeaderResponse response = obsClient.putObject("bucketName" ,"objectKey" ,fileStream); int statusCode = response.getStatusCode(); if (200 == statusCode) { return true ; } obsClient.close(); } catch (IOException e) { logger.info("文件上传失败:{}" , e.getMessage(), e); } return false ; } @GetMapping("/downloadFile") public boolean downloadFile () { ObsClient obsClient = null ; try { obsClient = new ObsClient (ak, sk, endPoint); ObsObject obsObject = obsClient.getObject(); 需要下载的桶名称以及对象名 String objectKey = obsObject.getObjectKey("bucketName" ,"objectKey" ); String filePath = "Q:\\Files\\" + objectKey; InputStream objectContent = obsObject.getObjectContent(); byte [] b = new byte [1024 ]; OutputStream outputStream = new FileOutputStream (filePath); int len; while ((len= objectContent.read(b)) != -1 ){ outputStream.write(b, 0 , len); } outputStream.close(); obsClient.close(); } catch (IOException e) { logger.info("文件上传失败:{}" , e.getMessage(), e); } return false ; } @GetMapping("/getUploadUrl") public String getUploadUrl () { ObsClient obsClient = null ; try { obsClient = new ObsClient (ak, sk, endPoint); long expireSeconds = 3600L ; Map<String, String> headers = new HashMap <String, String>(); headers.put("Content-Type" , "application/octet-stream" ); TemporarySignatureRequest request = new TemporarySignatureRequest (HttpMethodEnum.PUT, expireSeconds); request.setBucketName("bucketName" ); request.setObjectKey("objectKey" ); request.setHeaders(headers); TemporarySignatureResponse response = obsClient.createTemporarySignature(request); System.out.println(response.getSignedUrl()); return response.getSignedUrl(); } catch (Exception e) { logger.error("获取上传地址异常:{}" , e.getMessage(), e); } return null ; } }
putObject(String bucketName, String objectKey, InputStream input)传递参数
代码依次为bucketName–桶名称,objectKey–上传/下载时对象名,input上传内容
更多内容参加OBS的Java SDK