乐趣区

关于java:阿里云OSS-appendObject-获取-position

阿里云 OSS appendObject 获取 position

背景

我的项目有个需要,每次调用接口,都须要把一行的数据存储到阿里 OSS 的某个文件去,之后就去翻看 阿里 OSS 官网文档,发现个追加上传 appendObject 的刚好合乎需要。

SDK 版本

本文例子基于 SDK JAVA 版本

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.11.2</version>
</dependency>

官网例子

官网例子:

// Endpoint 以杭州为例,其它 Region 请按理论状况填写。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";

String content1 = "Hello OSS A \n";
String content2 = "Hello OSS B \n";
String content3 = "Hello OSS C \n";

// 创立 OSSClient 实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。meta.setContentType("text/plain");

// 通过 AppendObjectRequest 设置多个参数。AppendObjectRequest appendObjectRequest = new AppendObjectRequest("<yourBucketName>", "<yourObjectName>", new ByteArrayInputStream(content1.getBytes()),meta);

// 第一次追加。// 设置文件的追加地位。appendObjectRequest.setPosition(0L);
AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
// 文件的 64 位 CRC 值。此值依据 ECMA-182 规范计算得出。System.out.println(appendObjectResult.getObjectCRC());

// 第二次追加。// nextPosition 指明下一次申请中该当提供的 Position,即文件以后的长度。appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);

// 第三次追加。appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content3.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);

// 敞开 OSSClient。ossClient.shutdown();
        

问题发现

通过阿里云 oss 存储追加文件 appendObject 类型时,每次 append 都须要指定一个 position 参数,如果position 参数不对,还会报一个 OssExcetion , 内容如下:

那么问题来了,这个 position 要怎么获取呢?


position 获取

1. 同一个申请的屡次写入

​ 如果是在同一个办法追加多条,能够通过上一次的执行后果 AppendObjectResult 中的 appendObjectResult.getNextPosition() 办法获取下一次插入的 position 地位。

// 第二次追加。// nextPosition 指明下一次申请中该当提供的 Position,即文件以后的长度。appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);

2. 两次不同的申请

如果是两次不同的申请,阿里 OSS 有一个元数据 ObjectMetadata的保护,能够通过 HeadObject 中的

x-oss-next-append-position 获取。

String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String fileName = "<your fileName>";
String bucketName = "your bucketName"
    
// 创立 OSSClient 实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 创立 headObject 申请
HeadObjectRequest request = new HeadObjectRequest(bucketName, fileName);
ObjectMetadata objectMetadata = ossClient.headObject(request);
// 通过反射获取
Field metadataField = ObjectMetadata.class.getDeclaredField("metadata");
metadataField.setAccessible(true);
Map<String, Object> metadata = (Map<String, Object>) metadataField.get(objectMetadata);
String positionStr = (String) metadata.get("x-oss-next-append-position");
long position = Long.parseLong(positionStr);
System.out.println(position);

阐明:~~~~

  1. x-oss-next-append-position <font color=’red’> 只有在对于 Appendable 类型的 Object 才会返回此 Header</font>,指明下一次申请该当提供的 position。参考链接: headObject 返回值阐明
  2. x-oss-next-append-position ObjectMetadata 中 没有具体的 api 获取,寄存在ObjectMetadata 中的一个 Map 汇合中,这个 Map 属性是一个protected 关键字润饰的,不能间接获取。因而须要通过反射获取到 ObjectMetadata 中的 Map 汇合,而后通过 map.get(“x-oss-next-append-position”) 获取

后记

刚开始获取这个 position 走了不少弯路,次要是没有认真看过 OSS 官网文档,之前还试过一个在网上看到的说法,能够通过以下的形式获取,后果发现基本不行,时不时还是会报 OssException 异样。这才从新去看官网文档找解决办法。

这里也记录下,省得后来者持续采坑

<font size=”3″ color=”red”> 谬误的获取形式:</font>

// 判断文件是否存在
boolean exists = ossClient.doesObjectExist(bucketName, fileName);
long position = 0L;
if(exists){
    // 获取文件
    OSSObject cdrObject = ossClient.getObject(bucketName, fileName);
    InputStream objectInputStream = cdrObject.getObjectContent();
    // 间接获取输出流的 available 并不精确,会时不时报错
    position = objectInputStream.available();}

参考链接

阿里 OSS 官网文档
appendObject
oss 异样类型
headObject

原创不易,转载请注明出处!

退出移动版