Java SDK 的 uploadFile
接口支持将本地大文件通过断点续传的方式分片上传到 TOS。使用该接口时,您可以设置分片大小、上传分片的并发线程数、上传客户端限速、进度条、事件回调函数等。同时也支持在断点续传上传过程中,取消该上传任务。若出现网络异常等情况导致文件上传失败,您可再次调用该接口,从断点处续传上传未完成的部分。
tos:PutObject
权限,具体操作,请参见权限配置指南。uploadFile
接口支持的最大并发线程数为 1000,默认分片大小为 20MiB。以下代码展示 uploadFile
接口的基本使用方式。
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.TosServerException;
import com.volcengine.tos.model.object.UploadFileV2Input;
import com.volcengine.tos.model.object.UploadFileV2Output;
public class UploadFileExample {
public static void main(String[] args) {
String endpoint = "your endpoint";
String region = "your region";
String accessKey = System.getenv("TOS_ACCESS_KEY");
String secretKey = System.getenv("TOS_SECRET_KEY");
String bucketName = "bucket-example";
// 对象名,模拟 example_dir 下的 example_object.txt 文件
String objectKey = "example_dir/example_object.txt";
// uploadFilePath 设置待上传的本地文件路径,建议使用绝对路径,确保文件存在,不支持上传文件夹
String uploadFilePath = "example_dir/example_file.txt";
// taskNum 设置并发上传的并发数,范围为 1-1000,默认为 1
int taskNum = 5;
// partSize 设置文件分片大小,范围为 5MB-5GB,默认为 20MB
long partSize = 20 * 1024 * 1024;
// enableCheckpoint 设置是否开启断点续传功能,开启则会在本地记录上传进度
boolean enableCheckpoint = true;
// checkpointFilePath 设置断点续传记录文件存放位置,若不设置则默认在 uploadFilePath 路径下生成
// 其格式为 {uploadFilePath}.{bucket+objectKey 的 Base64Md5 值}.upload
String checkpointFilePath = "the checkpoint file path";
TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
try{
UploadFileV2Input input = new UploadFileV2Input().setBucket(bucketName).setKey(objectKey)
.setFilePath(uploadFilePath).setEnableCheckpoint(enableCheckpoint)
.setCheckpointFile(checkpointFilePath).setPartSize(partSize).setTaskNum(taskNum);
UploadFileV2Output output = tos.uploadFile(input);
System.out.println("uploadFile succeed, object's etag is " + output.getEtag());
System.out.println("uploadFile succeed, object's crc64 is " + output.getHashCrc64ecma());
} catch (TosClientException e) {
// 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送
System.out.println("uploadFile failed");
System.out.println("Message: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
} catch (TosServerException e) {
// 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息
System.out.println("uploadFile failed");
System.out.println("StatusCode: " + e.getStatusCode());
System.out.println("Code: " + e.getCode());
System.out.println("Message: " + e.getMessage());
System.out.println("RequestID: " + e.getRequestID());
} catch (Throwable t) {
// 作为兜底捕获其他异常,一般不会执行到这里
System.out.println("uploadFile failed");
System.out.println("unexpected exception, message: " + t.getMessage());
}
}
}
以下代码展示如何在断点续传上传过程中自定义监听回调函数。
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.TosServerException;
import com.volcengine.tos.comm.event.UploadEventType;
import com.volcengine.tos.model.object.*;
public class UploadFileWithEventListenerExample {
public static void main(String[] args) {
String endpoint = "your endpoint";
String region = "your region";
String accessKey = System.getenv("TOS_ACCESS_KEY");
String secretKey = System.getenv("TOS_SECRET_KEY");
String bucketName = "bucket-example";
// 对象名,模拟 example_dir 下的 example_object.txt 文件
String objectKey = "example_dir/example_object.txt";
// uploadFilePath 设置待上传的本地文件路径,建议使用绝对路径,确保文件存在,不支持上传文件夹
String uploadFilePath = "example_dir/example_file.txt";
// taskNum 设置并发上传的并发数,范围为 1-1000,默认为 1
int taskNum = 5;
// partSize 设置文件分片大小,范围为 5MB-5GB,默认为 20MB
long partSize = 20 * 1024 * 1024;
// enableCheckpoint 设置是否开启断点续传功能,开启则会在本地记录上传进度
boolean enableCheckpoint = true;
// checkpointFilePath 设置断点续传记录文件存放位置,若不设置则默认在 uploadFilePath 路径下生成
// 其格式为 {uploadFilePath}.{bucket+objectKey 的 Base64Md5 值}.upload
String checkpointFilePath = "the checkpoint file path";
TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
try{
UploadEventListener listener = new UploadEventListener() {
// 自定义实现 UploadEventListener 的 eventChange 接口,监听断点续传上传事件,SDK 会进行回调
@Override
public void eventChange(UploadEvent uploadEvent) {
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventCreateMultipartUploadSucceed) {
System.out.println("event change, createMultipartUpload succeed");
}
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventCreateMultipartUploadFailed) {
System.out.println("event change, createMultipartUpload failed");
}
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventUploadPartSucceed) {
System.out.println("event change, uploadPart succeed");
}
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventUploadPartFailed) {
System.out.println("event change, uploadPart failed");
}
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventUploadPartAborted) {
System.out.println("event change, uploadPart aborted");
}
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventCompleteMultipartUploadSucceed) {
System.out.println("event change, completeMultipartUpload succeed");
}
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventCompleteMultipartUploadFailed) {
System.out.println("event change, completeMultipartUpload failed");
}
}
};
UploadFileV2Input input = new UploadFileV2Input().setBucket(bucketName).setKey(objectKey)
.setFilePath(uploadFilePath).setEnableCheckpoint(enableCheckpoint)
.setCheckpointFile(checkpointFilePath).setPartSize(partSize).setTaskNum(taskNum)
.setUploadEventListener(listener);
UploadFileV2Output output = tos.uploadFile(input);
System.out.println("uploadFile succeed, object's etag is " + output.getEtag());
System.out.println("uploadFile succeed, object's crc64 is " + output.getHashCrc64ecma());
} catch (TosClientException e) {
// 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送
System.out.println("uploadFile failed");
System.out.println("Message: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
} catch (TosServerException e) {
// 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息
System.out.println("uploadFile failed");
System.out.println("StatusCode: " + e.getStatusCode());
System.out.println("Code: " + e.getCode());
System.out.println("Message: " + e.getMessage());
System.out.println("RequestID: " + e.getRequestID());
} catch (Throwable t) {
// 作为兜底捕获其他异常,一般不会执行到这里
System.out.println("uploadFile failed");
System.out.println("unexpected exception, message: " + t.getMessage());
}
}
}
断点续传过程中,SDK 支持取消上传任务。以下代码展示如何取消正在执行的断点续传上传任务。
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.TosServerException;
import com.volcengine.tos.comm.event.UploadEventType;
import com.volcengine.tos.model.object.*;
public class UploadFileWithCancelExample {
public static void main(String[] args) {
String endpoint = "your endpoint";
String region = "your region";
String accessKey = System.getenv("TOS_ACCESS_KEY");
String secretKey = System.getenv("TOS_SECRET_KEY");
String bucketName = "bucket-example";
// 对象名,模拟 example_dir 下的 example_object.txt 文件
String objectKey = "example_dir/example_object.txt";
// uploadFilePath 设置待上传的本地文件路径,建议使用绝对路径,确保文件存在,不支持上传文件夹
String uploadFilePath = "example_dir/example_file.txt";
// taskNum 设置并发上传的并发数,范围为 1-1000,默认为 1
int taskNum = 5;
// partSize 设置文件分片大小,范围为 5MB-5GB,默认为 20MB
long partSize = 20 * 1024 * 1024;
// enableCheckpoint 设置是否开启断点续传功能,开启则会在本地记录上传进度
boolean enableCheckpoint = true;
// checkpointFilePath 设置断点续传记录文件存放位置,若不设置则默认在 uploadFilePath 路径下生成
// 其格式为 {uploadFilePath}.{bucket+objectKey 的 Base64Md5 值}.upload
String checkpointFilePath = "the checkpoint file path";
TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
try{
UploadFileV2Input input = new UploadFileV2Input().setBucket(bucketName).setKey(objectKey)
.setFilePath(uploadFilePath).setEnableCheckpoint(enableCheckpoint)
.setCheckpointFile(checkpointFilePath).setPartSize(partSize).setTaskNum(taskNum);
// 以下代码通过 UploadEventListener 监听上传事件。
// 如果出现 UploadEventUploadPartFailed 事件,即有上传失败的分片时就终止上传任务。
// 以下代码仅作为示例,用户可根据业务需要进行使用。
boolean isAbort = true;
UploadEventListener listener = new UploadEventListener() {
@Override
public void eventChange(UploadEvent uploadEvent) {
if (uploadEvent.getUploadEventType() == UploadEventType.UploadEventUploadPartFailed) {
System.out.println("event change, uploadPart failed");
if (input.getCancelHook() != null) {
// 调用 cancel 时,如果 isAbort 为 true,会终止断点续传,删除本地 checkpoint 文件,
// 并调用 abortMultipartUpload 取消分片上传。
// 如果 isAbort 为 false,只会暂停当前上传任务,再次调用 uploadFile 可从断点处续传。
input.getCancelHook().cancel(isAbort);
}
}
}
};
input.setCancelHook(true).setUploadEventListener(listener);
UploadFileV2Output output = tos.uploadFile(input);
System.out.println("uploadFile succeed, object's etag is " + output.getEtag());
System.out.println("uploadFile succeed, object's crc64 is " + output.getHashCrc64ecma());
} catch (TosClientException e) {
// 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送
System.out.println("uploadFile failed");
System.out.println("Message: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
} catch (TosServerException e) {
// 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息
System.out.println("uploadFile failed");
System.out.println("StatusCode: " + e.getStatusCode());
System.out.println("Code: " + e.getCode());
System.out.println("Message: " + e.getMessage());
System.out.println("RequestID: " + e.getRequestID());
} catch (Throwable t) {
// 作为兜底捕获其他异常,一般不会执行到这里
System.out.println("uploadFile failed");
System.out.println("unexpected exception, message: " + t.getMessage());
}
}
}
以下代码展示如何使用进度条功能和设置上传客户端限速。
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.TosServerException;
import com.volcengine.tos.comm.event.DataTransferListener;
import com.volcengine.tos.comm.event.DataTransferStatus;
import com.volcengine.tos.comm.event.DataTransferType;
import com.volcengine.tos.comm.ratelimit.RateLimiter;
import com.volcengine.tos.internal.util.ratelimit.DefaultRateLimiter;
import com.volcengine.tos.model.object.ObjectMetaRequestOptions;
import com.volcengine.tos.model.object.UploadFileV2Input;
import com.volcengine.tos.model.object.UploadFileV2Output;
import java.io.File;
public class UploadFileWithProgressAndRateLimiterExample {
public static void main(String[] args) {
String endpoint = "your endpoint";
String region = "your region";
String accessKey = System.getenv("TOS_ACCESS_KEY");
String secretKey = System.getenv("TOS_SECRET_KEY");
String bucketName = "bucket-example";
// 对象名,模拟 example_dir 下的 example_object.txt 文件
String objectKey = "example_dir/example_object.txt";
// uploadFilePath 设置待上传的本地文件路径,建议使用绝对路径,确保文件存在,不支持上传文件夹
String uploadFilePath = "example_dir/example_file.txt";
// taskNum 设置并发上传的并发数,范围为 1-1000,默认为 1
int taskNum = 5;
// partSize 设置文件分片大小,范围为 5MB-5GB,默认为 20MB
long partSize = 20 * 1024 * 1024;
// enableCheckpoint 设置是否开启断点续传功能,开启则会在本地记录上传进度
boolean enableCheckpoint = true;
// checkpointFilePath 设置断点续传记录文件存放位置,若不设置则默认在 uploadFilePath 路径下生成
// 其格式为 {uploadFilePath}.{bucket+objectKey 的 Base64Md5 值}.upload
String checkpointFilePath = "the checkpoint file path";
TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
try{
UploadFileV2Input input = new UploadFileV2Input().setBucket(bucketName).setKey(objectKey)
.setFilePath(uploadFilePath).setEnableCheckpoint(enableCheckpoint)
.setCheckpointFile(checkpointFilePath).setPartSize(partSize).setTaskNum(taskNum);
// 以下代码展示如何处理进度条
// 在 ObjectMetaRequestOptions 中设置文件大小,可在进度条中显示 total 总长度,否则 DataTransferStatus.getTotalBytes 值为 -1。
ObjectMetaRequestOptions options = new ObjectMetaRequestOptions().setContentLength(new File(uploadFilePath).length());
input.setOptions(options);
// 自定义实现 DataTransferListener,实现进度条功能
DataTransferListener listener = getDataTransferListener();
input.setDataTransferListener(listener);
// 以下代码展示如何设置客户端限速
// 配置上传对象最大限速为 20MB/s,平均限速为 5MB/s。
RateLimiter limiter = new DefaultRateLimiter(20 * 1024 * 1024, 5 * 1024 * 1024);
input.setRateLimiter(limiter);
UploadFileV2Output output = tos.uploadFile(input);
System.out.println("uploadFile succeed, object's etag is " + output.getEtag());
System.out.println("uploadFile succeed, object's crc64 is " + output.getHashCrc64ecma());
} catch (TosClientException e) {
// 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送
System.out.println("uploadFile failed");
System.out.println("Message: " + e.getMessage());
if (e.getCause() != null) {
e.getCause().printStackTrace();
}
} catch (TosServerException e) {
// 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息
System.out.println("uploadFile failed");
System.out.println("StatusCode: " + e.getStatusCode());
System.out.println("Code: " + e.getCode());
System.out.println("Message: " + e.getMessage());
System.out.println("RequestID: " + e.getRequestID());
} catch (Throwable t) {
// 作为兜底捕获其他异常,一般不会执行到这里
System.out.println("uploadFile failed");
System.out.println("unexpected exception, message: " + t.getMessage());
}
}
private static DataTransferListener getDataTransferListener() {
return new DataTransferListener() {
// 自定义实现 DataTransferListener 的 dataTransferStatusChange 接口
@Override
public void dataTransferStatusChange(DataTransferStatus dataTransferStatus) {
if (dataTransferStatus.getType() == DataTransferType.DATA_TRANSFER_STARTED) {
System.out.println("uploadFile started.");
} else if (dataTransferStatus.getType() == DataTransferType.DATA_TRANSFER_RW) {
System.out.printf("uploadFile, send %d bytes once, has sent %d bytes, total %d bytes.\n",
dataTransferStatus.getRwOnceBytes(), dataTransferStatus.getConsumedBytes(),
dataTransferStatus.getTotalBytes());
} else if (dataTransferStatus.getType() == DataTransferType.DATA_TRANSFER_FAILED) {
System.out.printf("uploadFile failed, has sent %d bytes, total %d bytes.\n",
dataTransferStatus.getConsumedBytes(), dataTransferStatus.getTotalBytes());
} else if (dataTransferStatus.getType() == DataTransferType.DATA_TRANSFER_SUCCEED) {
System.out.printf("uploadFile succeed, has sent %d bytes, total %d bytes.\n",
dataTransferStatus.getConsumedBytes(), dataTransferStatus.getTotalBytes());
}
}
};
}
}