SDK 支持通过 appendObject 接口追加写对象。追加写是指在已上传的对象末尾追加内容,只能对类型为 Appendable 的对象使用此接口。通过直接上传或分片上传创建的对象类型为 Normal,而通过 appendObject 接口上传的对象为 Appendable 类型。
使用 appendObject 接口时, 对象的大小限制说明如下:
以下代码展示如何追加写对象到目标桶中。
import android.os.Bundle; import android.util.Log; import androidx.appcompat.app.AppCompatActivity; import com.volcengine.tos.TOSV2; import com.volcengine.tos.TOSV2ClientBuilder; import com.volcengine.tos.TosException; import com.volcengine.tos.comm.common.ACLType; import com.volcengine.tos.comm.common.StorageClassType; import com.volcengine.tos.model.object.AppendObjectInput; import com.volcengine.tos.model.object.AppendObjectOutput; import com.volcengine.tos.model.object.ObjectMetaRequestOptions; import java.io.ByteArrayInputStream; import java.util.Arrays; import java.util.HashMap; import java.util.Map; public class AppendObjectExample extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { String endpoint = "your endpoint"; String region = "your region"; String accessKey = "your access key"; String secretKey = "your secret key"; String securityToken = "your security token"; String bucketName = "your bucket name"; String objectKey = "your object key"; super.onCreate(savedInstanceState); setContentView(R.layout.activity_display_message); TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey, securityToken); Thread tosThread = new Thread(new Runnable() { @Override public void run() { try{ // 第一次追加写,请确保传输的数据长度大于等于 128KB byte[] data1 = new byte[128 * 1024]; Arrays.fill(data1, (byte) 'A'); ByteArrayInputStream stream = new ByteArrayInputStream(data1); // 如果需要设置 appendable 对象的元数据,可在第一次追加写的时候设置,后续无需再添加 ObjectMetaRequestOptions options = new ObjectMetaRequestOptions(); // 设置对象访问权限,此处为私有权限 options.setAclType(ACLType.ACL_PRIVATE); // 设置对象存储类型 options.setStorageClass(StorageClassType.STORAGE_CLASS_STANDARD); // SDK 默认会根据 objectKey 后缀识别 Content-Type,也可以自定义设置 options.setContentType("application/json"); // 自定义对象的元数据,对于自定义的元数据,SDK 会自动对 key 添加 // "X-Tos-Meta-" 的前缀,因此用户无需自行添加。 Map<String, String> custom = new HashMap<>(); custom.put("name", "volc_user"); // 在 TOS 服务端存储的元数据为:"X-Tos-Meta-name: volc_user" options.setCustomMetadata(custom); // 注意:当前 TOS 使用 appendObject 接口时需要传入数据长度和偏移量 long contentLength = data1.length; long offset = 0; AppendObjectInput input = new AppendObjectInput().setBucket(bucketName).setKey(objectKey) .setContent(stream).setContentLength(contentLength).setOffset(offset).setOptions(options); AppendObjectOutput output = tos.appendObject(input); Log.i("appendObject", "appendObject first time succeed, object's nextAppendOffset is " + output.getNextAppendOffset()); Log.i("appendObject", "appendObject first time succeed, object's crc64 is " + output.getHashCrc64ecma()); // 第二次追加写 byte[] data2 = new byte[128 * 1024 + 1024]; Arrays.fill(data2, (byte) 'B'); // 偏移量为当前对象的长度,即从对象末尾追加写数据。 contentLength = data2.length; offset = data1.length; // 由于 SDK 默认开启 crc64 校验,从第二次追加写开始,之后每次调用都需要传入上一次追加写请求返回的 crc64 值。 String preHashCrc64 = output.getHashCrc64ecma(); input = new AppendObjectInput().setBucket(bucketName).setKey(objectKey).setContent(new ByteArrayInputStream(data2)) .setOffset(offset).setContentLength(contentLength).setPreHashCrc64ecma(preHashCrc64); output = tos.appendObject(input); Log.i("appendObject", "appendObject second time succeed, object's nextAppendOffset is " + output.getNextAppendOffset()); Log.i("appendObject", "appendObject second time succeed, object's crc64 is " + output.getHashCrc64ecma()); // 第三次追加写 byte[] data3 = new byte[256 * 1024 + 1024]; Arrays.fill(data3, (byte) 'C'); // 偏移量为当前对象的长度,即从对象末尾追加写数据。 contentLength = data3.length; offset = data1.length + data2.length; // 由于 SDK 默认开启 crc64 校验,从第二次追加写开始,之后每次调用都需要传入上一次追加写请求返回的 crc64 值。 preHashCrc64 = output.getHashCrc64ecma(); input = new AppendObjectInput().setBucket(bucketName).setKey(objectKey).setContent(new ByteArrayInputStream(data3)) .setOffset(offset).setContentLength(contentLength).setPreHashCrc64ecma(preHashCrc64); output = tos.appendObject(input); Log.i("appendObject", "appendObject third time succeed, object's nextAppendOffset is " + output.getNextAppendOffset()); Log.i("appendObject", "appendObject third time succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (TosException e) { Log.e("TosException", "appendObject failed"); e.printStackTrace(); } } }); tosThread.start(); } }
关于追加上传的 API 文档,请参见 AppendObject。