普通上传是指通过 TOS Java SDK 的 putObject
接口上传单个对象(Object)。SDK 统一使用 InputStream 类作为上传的数据流参数。您可根据业务需要使用不同形式的数据流传入,如上传字符串或字节数组可以使用 ByteArrayInputStream,上传文件可以使用 FileInputStream 等。本文将给出上传不同数据流的使用说明和示例代码,供您参考。
tos:PutObject
权限,具体操作,请参见权限配置指南。以下代码展示如何将字符串上传到目标桶 bucket-example
中的 example_dir
目录下的 example_object.txt
文件。
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.PutObjectInput; import com.volcengine.tos.model.object.PutObjectOutput; import java.io.ByteArrayInputStream; public class PutObjectWithByteArrayInputStreamExample { 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"; String objectKey = "example_dir/example_object.txt"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); try{ // 上传的数据内容,以 String 的形式 String data = "1234567890abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+<>?,./ :'1234567890abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+<>?,./ :'"; // 也可以以 byte 数组的形式上传 byte[] dataInBytes = data.getBytes(); // 统一封装成 ByteArrayInputStream ByteArrayInputStream stream = new ByteArrayInputStream(dataInBytes); PutObjectInput putObjectInput = new PutObjectInput() .setBucket(bucketName).setKey(objectKey).setContent(stream); PutObjectOutput output = tos.putObject(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject failed"); System.out.println("unexpected exception, message: " + t.getMessage()); } } }
通过 Java SDK 上传本地文件有两种方式,一是将一个打开的 FileInputStream 文件流对象作为参数传入 putObject
接口,二是将待上传的文件路径或 File 对象作为参数传入 putObjectFromFile
接口。
以下代码展示如何使用 putObject
接口将一个本地文件 example_dir/example_file.txt
上传到目标桶 bucket-example
中的 example_dir
目录下的 example_object.txt
文件。
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.PutObjectInput; import com.volcengine.tos.model.object.PutObjectOutput; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class PutObjectWithFileInputStreamExample { 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"; // 本地文件路径,请保证文件存在,暂不支持文件夹功能 String filePath = "example_dir/example_file.txt"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); File file = new File(filePath); try(FileInputStream inputStream = new FileInputStream(file)){ PutObjectInput putObjectInput = new PutObjectInput().setBucket(bucketName) .setKey(objectKey).setContent(inputStream).setContentLength(file.length()); PutObjectOutput output = tos.putObject(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (IOException e) { System.out.println("putObject read file failed"); e.printStackTrace(); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject failed"); System.out.println("unexpected exception, message: " + t.getMessage()); } } }
以下代码展示如何使用 putObjectFromFile
接口将一个本地文件 example_file.txt
上传到目标桶 bucket-example
中的 example_dir
目录下的 example_object.txt
文件。
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.PutObjectFromFileInput; import com.volcengine.tos.model.object.PutObjectFromFileOutput; public class PutObjectFromFileExample { 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"; // 本地文件路径,请保证文件存在,暂不支持文件夹功能 String filePath = "example_dir/example_file.txt"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); try { PutObjectFromFileInput putObjectInput = new PutObjectFromFileInput() .setBucket(bucketName).setKey(objectKey).setFilePath(filePath); PutObjectFromFileOutput output = tos.putObjectFromFile(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject failed"); System.out.println("unexpected exception, message: " + t.getMessage()); } } }
Java SDK 的 putObject
接口支持将网络中的资源上传到 TOS 中。以下代码展示如何将一个网络流上传到目标桶 bucket-example
中的 example_dir
目录下的 example_object.txt
文件。
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.PutObjectInput; import com.volcengine.tos.model.object.PutObjectOutput; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; public class PutObjectWithUrlExample { 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"; // 待上传的网络流地址 String url = "https://www.volcengine.com/"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); try(InputStream inputStream = new BufferedInputStream(new URL(url).openStream())){ PutObjectInput putObjectInput = new PutObjectInput().setBucket(bucketName).setKey(objectKey).setContent(inputStream); PutObjectOutput output = tos.putObject(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (IOException e) { System.out.println("putObject read data from url failed"); e.printStackTrace(); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject failed"); System.out.println("unexpected exception, message: " + t.getMessage()); } } }
使用 putObject
或 putObjectFromFile
接口上传对象数据时,SDK 还支持设置对象的元数据信息,如指定对象的访问控制 ACL,存储类型 StorageClass,或者自定义对象的元数据等。
以下代码展示如何在 putObject
时设置对象的元数据信息。注意此处的设置非必选,请根据业务实际需求进行选择。
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.common.ACLType; import com.volcengine.tos.comm.common.StorageClassType; import com.volcengine.tos.model.object.ObjectMetaRequestOptions; import com.volcengine.tos.model.object.PutObjectInput; import com.volcengine.tos.model.object.PutObjectOutput; import java.io.ByteArrayInputStream; import java.util.HashMap; import java.util.Map; public class PutObjectWithMetaOptionsExample { 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"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); try{ String data = "1234567890abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+<>?,./ :'1234567890abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+<>?,./ :'"; ByteArrayInputStream stream = new ByteArrayInputStream(data.getBytes()); ObjectMetaRequestOptions options = new ObjectMetaRequestOptions(); // 以下所有设置参数均为可选,参数值仅供参考,请根据业务实际需要进行设置。 // 设置对象访问权限,此处为私有权限 options.setAclType(ACLType.ACL_PRIVATE); // 设置对象存储类型 options.setStorageClass(StorageClassType.STORAGE_CLASS_STANDARD); // SDK 默认会根据 objectKey 后缀识别 Content-Type,也可以自定义设置 options.setContentType("text/plain"); // 设置对象MD5,用于服务端校验数据是否与客户端传输的一致。此 MD5 值需要您自行计算传入 options.setContentMD5("yjtlyPoGKxvDj+QOPocqjg=="); // 自定义对象的元数据,对于自定义的元数据,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); PutObjectInput putObjectInput = new PutObjectInput().setBucket(bucketName).setKey(objectKey) .setOptions(options).setContent(stream); PutObjectOutput output = tos.putObject(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject 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.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class PutObjectWithProgressAndRateLimiterExample { 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"; // 本地文件路径,请保证文件存在,暂不支持文件夹功能 String filePath = "example_dir/example_file.txt"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); try(FileInputStream inputStream = new FileInputStream(filePath)){ PutObjectInput putObjectInput = new PutObjectInput().setBucket(bucketName).setKey(objectKey).setContent(inputStream); // 以下代码展示如何处理进度条 // 在 ObjectMetaRequestOptions 中设置文件大小,可在进度条中显示 total 总长度,否则 DataTransferStatus.getTotalBytes 值为 -1。 ObjectMetaRequestOptions options = new ObjectMetaRequestOptions().setContentLength(new File(filePath).length()); putObjectInput.setOptions(options); // 自定义实现 DataTransferListener,实现进度条功能 DataTransferListener listener = getDataTransferListener(); putObjectInput.setDataTransferListener(listener); PutObjectOutput output = tos.putObject(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (IOException e) { System.out.println("putObject read file failed"); e.printStackTrace(); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject 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("putObject started."); } else if (dataTransferStatus.getType() == DataTransferType.DATA_TRANSFER_RW) { System.out.printf("putObject, 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("putObject failed, has sent %d bytes, total %d bytes.\n", dataTransferStatus.getConsumedBytes(), dataTransferStatus.getTotalBytes()); } else if (dataTransferStatus.getType() == DataTransferType.DATA_TRANSFER_SUCCEED) { System.out.printf("putObject succeed, has sent %d bytes, total %d bytes.\n", dataTransferStatus.getConsumedBytes(), dataTransferStatus.getTotalBytes()); } } }; } }
TOS Java SDK 当前不支持批量上传指定文件夹中的文件的功能,您可自行遍历本地文件夹进行逐个文件的上传。
以下代码展示如何遍历上传指定文件夹中的一批文件。为提升上传效率,代码中以 100MiB 的大小作为阈值,小于 100MiB 的文件直接通过 putObjectFromFile
接口上传,大于等于 100MiB 的文件通过 uploadFile
接口进行断点续传上传。100MiB 仅作为参考值,您可根据客户端的网络带宽等资源情况进行调整。
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.*; import java.io.File; import java.util.ArrayList; import java.util.List; public class UploadFileWithDirectoryExample { 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"; // uploadFileDirectory 设置待上传的本地文件夹,建议使用绝对路径 String uploadFileDirectory = "example_dir"; // 以 100MB 作为阈值,大于等于此阈值使用 uploadFile 接口上传,小于则使用 putObjectFromFile 上传 // 此值仅供参考,请根据客户端资源情况进行调整 long threshold = 100 * 1024 * 1024; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); List<String> fileList = getFileListFromPath(uploadFileDirectory); if (fileList == null || fileList.size() == 0) { System.out.println("uploadFile done, there are no files under " + uploadFileDirectory); return; } for (String file : fileList) { // 循环遍历文件夹下面的文件,使用文件名作为对象名进行上传。 if (new File(file).length() >= threshold) { uploadLargeFile(tos, bucketName, file); } else { uploadSmallFile(tos, bucketName, file); } } } private static void uploadSmallFile(TOSV2 tos, String bucketName, String file) { try { PutObjectFromFileInput putObjectInput = new PutObjectFromFileInput().setBucket(bucketName).setKey(file).setFilePath(file); PutObjectFromFileOutput output = tos.putObjectFromFile(putObjectInput); System.out.println("putObject succeed, object's etag is " + output.getEtag()); System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("putObject failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("putObject 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("putObject failed"); System.out.println("unexpected exception, message: " + t.getMessage()); } } private static void uploadLargeFile(TOSV2 tos, String bucketName, String file) { // taskNum 设置并发上传的并发数,范围为 1-1000,默认为 1 int taskNum = 5; // partSize 设置文件分片大小,范围为 5MB-5GB,默认为 20MB long partSize = 20 * 1024 * 1024; // enableCheckpoint 设置是否开启断点续传功能,开启则会在本地记录上传进度 boolean enableCheckpoint = true; // checkpointFilePath 设置断点续传记录文件存放位置,若不设置则默认在 uploadFileDirectory 路径下生成 // 其格式为 {uploadFileDirectory}.{bucket+objectKey 的 Base64Md5 值}.upload String checkpointFilePath = "the checkpoint file path"; try{ UploadFileV2Input input = new UploadFileV2Input().setBucket(bucketName).setKey(file) .setFilePath(file).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()); } } private static List<String> getFileListFromPath(String filePath) { List<String> fileList = new ArrayList<>(); File file = new File(filePath); if (!file.exists()) { return fileList; } File[] files = file.listFiles(); if (files == null || files.length == 0) { return fileList; } for (File f : files) { if (f.isDirectory()) { fileList.addAll(getFileListFromPath(f.getPath())); } else { fileList.add(f.getPath()); } } return fileList; } }
关于上传对象的 API 文档,请参见 PutObject。