阿里云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);
阐明:~~~~
x-oss-next-append-position
<font color='red'>只有在对于Appendable类型的Object才会返回此Header</font>,指明下一次申请该当提供的position。参考链接: headObject 返回值阐明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
原创不易,转载请注明出处!