File management
Upload files
In BOS, the basic data unit for user operations is an object. An object consists of a key, metadata, and data. The key is the object’s name, the metadata provides a user-defined description as a set of name-value pairs, and the data is the content of the object.
The BOS Java SDK provides a rich set of file upload APIs, and files can be uploaded in the following ways:
- Simple upload
- Append upload
- Multipart upload
- Resumable upload
Simple upload
In simple upload scenarios, BOS supports uploading objects in the form of specified files, data streams, binary strings, and character strings. Please refer to the following code or Simple Upload Demo.
1public void PutObject(BosClient client, String bucketName, String objectKey, byte[] byte1, String string1){
2 // Get specified file
3 File file = new File("/path/to/file.zip");
4 // Obtain data stream
5 InputStream inputStream = new FileInputStream("/path/to/test.zip");
6
7 // Upload object as a file
8 PutObjectResponse putObjectFromFileResponse = client.putObject(bucketName, objectKey, file);
9 // Upload an object in the form of a data stream
10 PutObjectResponse putObjectResponseFromInputStream = client.putObject(bucketName, objectKey, inputStream);
11 // Upload object as binary string
12 PutObjectResponse putObjectResponseFromByte = client.putObject(bucketName, objectKey, byte1);
13 // Upload object in string form
14 PutObjectResponse putObjectResponseFromString = client.putObject(bucketName, objectKey, string1);
15 // Create an empty directory. The objectKey must end with a forward slash, such as test/
16 // The BOS console will, by default, display objects ending with a forward slash (/) as file directories
17 PutObjectResponse putObjectResponseFromString = client.putObject(bucketName, objectKey, "");
18
19 // Print ETag
20 System.out.println(putObjectFromFileResponse.getETag());
21}
Files are uploaded to BOS as objects. The PutObject function supports uploading objects with a size of up to 5 GB. Upon successful processing of a PutObject request, BOS returns the object's ETag in the response header as its unique identifier.
Set file meta information
Object metadata refers to the attributes of files provided by users when uploading to BOS. It is mainly divided into two categories: standard HTTP attribute settings (HTTP headers) and user-defined metadata.
- Set Http header of object
The BOS Java SDK essentially interacts with the backend HTTP API, allowing users to customize the HTTP headers of the object when uploading files. The following describes some commonly used HTTP headers:
| Name | Description | Default value |
|---|---|---|
| Content-MD5 | File data verification: After setting, BOS will enable file content MD5 verification, compare the MD5 you provide with the MD5 of the file, and throw an error if they are inconsistent | None |
| Content-Type | File MIME: This defines the file type and web page encoding, determining how the browser reads the file. If unspecified, BOS generates it based on the file's extension. If the file lacks an extension, a default value will be applied. | application/octet-stream |
| Content-Disposition | Indicate how the MIME user agent displays the attached file, whether to open or download it, and the file name | None |
| Content-Length | The length of the uploaded file. If it exceeds the length of the stream/file, it will be truncated; if it is insufficient, it will be the actual value | Stream/file duration |
| Expires | Cache expiration time | None |
| Cache-Control | Specify the caching behavior of the web page when the object is downloaded | None |
| x-bce-content-crc32 | The CRC value (cyclic redundancy check code) of uploaded object | None |
Reference code is as follows:
1//Initialize the upload input stream
2ObjectMetadata meta = new ObjectMetadata();
3 // Set ContentLength size
4meta.setContentLength(1000);
5 // Set ContentType
6meta.setContentType("application/json");
7 //Set cache-control
8meta.setCacheControl("no-cache");
9 // Set x-bce-content-crc32. The file’s CRC32 check code must be calculated by the user themselves
10meta.setxBceCrc("0x74E947D0");
11client.putObject(bucketName, objectKey, content, meta);
- Set file meta information
BOS lets users set object ACL permissions during upload, with options like “private” and “public-read,” as shown in the following code:
1// Set ACL to private
2PutObjectRequest request = new PutObjectRequest(bucketName, key, file);
3request.setxBceAcl("private");
4
5 // Upload Object
6client.putObject(bucketName, objectKey, content, meta);
- User-defined meta information
BOS supports user-defined metadata for describing objects. Example usage is shown in the following code:
1// Set the value of custom metadata name to my-data
2meta.addUserMetadata("name", "my-data");
3
4 // Upload Object
5client.putObject(bucketName, objectKey, content, meta);
Prompt:
- In the above code, the user has customized a metadata with the name "name" and value "my-data".
- When users download this object, this metadata can also be obtained.
- An object may have multiple similar parameters, but the total size of all user meta must not exceed 2KB.
Set storage class when uploading an object
BOS supports standard storage, infrequent access storage, and cold storage. Uploading an object and storing it as an infrequent access storage class is achieved by specifying the StorageClass. The parameters corresponding to the three storage classes are as follows:
| Storage class | Parameters |
|---|---|
| Standard storage | STANDRAD |
| Infrequent access storage | STANDARD_IA |
| Cold storage | COLD |
Taking infrequent access storage as an example, the code is as follows:
1public void putObjectStorageClass(){
2 PutObjectRequest request = new PutObjectRequest(bucketName, key, file);
3 request.withStorageClass(BosClient.STORAGE_CLASS_STANDARD_IA);
4 client.putObject(request);
5}
Append upload
Objects created using the simple upload method described above are all of a standard type and do not support append writes. This limitation can be inconvenient in scenarios where frequent data overwriting occurs, such as log files, video surveillance, and live video streaming.
To address this, Baidu AI Cloud Object Storage (BOS) specifically supports the AppendObject method, which allows files to be uploaded in an append-write fashion. Objects created through the AppendObject operation are categorized as Appendable Objects, enabling data to be appended to them. The size limit for AppendObject files is 0–5 GB.
The sample code for uploading via the AppendObject method is as follows, or refer to Append Upload Demo.
1public void AppendObject(BosClient client, String bucketName, String objectKey, byte[] byte1, String string1) {
2 // Get specified file
3 File file = new File("/path/to/file.zip");
4 // Obtain data stream
5 InputStream inputStream = new FileInputStream("/path/to/test.zip");
6 // Upload object as a file
7 AppendObjectResponse appendObjectFromFileResponse = client.appendObject(bucketName, objectKey, file);
8 // Upload an object in the form of a data stream
9 AppendObjectResponse appendObjectResponseFromInputStream = client.appendObject(bucketName, objectKey, inputStream);
10 // Upload object as binary string
11 AppendObjectResponse appendObjectResponseFromByte = client.appendObject(bucketName, objectKey, byte1);
12 // Upload object in string form
13 AppendObjectResponse appendObjectResponseFromString = client.appendObject(bucketName, objectKey, string1);
14 // Print ETag
15 System.out.println(appendObjectFromFileResponse.getETag());
16 //Print NextAppendOffset
17 System.out.println(appendObjectFromFileResponse.getNextAppendOffset());
18 // Print ContentMd5
19 System.out.println(appendObjectFromFileResponse.getContentMd5());
20 //Example of append upload, need to add the position of the next append write in the request
21 Long nextAppendOffset = appendObjectFromFileResponse.getNextAppendOffset();
22 AppendObjectRequest appendObjectFromFileRequest = new AppendObjectRequest(bucketName,objectKey,file);
23 appendObjectFromFileRequest.setOffset(nextAppendOffset);
24 AppendObjectResponse appendObjectFromFileResponse = client.appendObject(appendObjectFromFileRequest);
25 }
Multipart upload
Besides uploading files to BOS using simple upload and append upload modes, BOS also supports another option—Multipart Upload. Users can use Multipart Upload mode in various scenarios, including but not limited to the ones below:
- When resumable uploads are required.
- When uploading files larger than 5GB.
- When the connection to the BOS server is frequently interrupted due to unstable network conditions.
- Enable streaming file uploads.
- The file size cannot be determined before uploading.
The following will introduce the implementation of Multipart Upload step by step. Suppose there is a file with the local path /path/to/file.zip. Since the file is large, it will be transmitted to BOS in parts. Or refer to Multipart Upload Demo
Initialize multipart upload
Use initiateMultipartUpload method to initialize a multipart upload event:
1// Initiate Multipart Upload
2InitiateMultipartUploadRequest initiateMultipartUploadRequest =
3 new InitiateMultipartUploadRequest(bucketName, objectKey);
4InitiateMultipartUploadResponse initiateMultipartUploadResponse =
5 client.initiateMultipartUpload(initiateMultipartUploadRequest);
6
7 // Print UploadId
8System.out.println("UploadId: " + initiateMultipartUploadResponse.getUploadId());
The return result of initiateMultipartUpload contains UploadId, which is the unique identifier for distinguishing multipart upload events, and we will use it in subsequent operations.
- Initialization for uploading infrequent access storage class objects
Initialize a multipart upload event for infrequent access storage:
1public void putMultiUploadStorageClass(){
2 InitiateMultipartUploadRequest iniReq = new InitiateMultipartUploadRequest(bucketName, key);
3 iniReq.withStorageClass(BosClient.STORAGE_CLASS_STANDARD_IA);
4 client.initiateMultipartUpload(iniReq);
5}
- Initialization for uploading a cold storage class object
Initialize a multipart upload event for infrequent access storage:
1public void putMultiUploadStorageClass(){
2 InitiateMultipartUploadRequest iniReq = new InitiateMultipartUploadRequest(bucketName, key);
3 iniReq.withStorageClass(BosClient.STORAGE_CLASS_COLD);
4 client.initiateMultipartUpload(iniReq);
5}
Upload parts
The file is then uploaded in multiple parts.
1// Set each part to 5MB
2final long partSize = 1024 * 1024 * 5L;
3
4File partFile = new File("/path/to/file.zip");
5
6 // Calculate the count of parts
7int partCount = (int) (partFile.length() / partSize);
8if (partFile.length() % partSize != 0){
9 partCount++;
10}
11
12 // Create a list to save the ETag and PartNumber of each uploaded part
13List<PartETag> partETags = new ArrayList<PartETag>();
14
15for(int i = 0; i < partCount; i++){
16 // Get file stream
17 FileInputStream fis = new FileInputStream(partFile);
18
19 //Jump to the beginning of each part
20 long skipBytes = partSize * i;
21 fis.skip(skipBytes);
22
23 // Calculate the size of each part
24 long size = partSize < partFile.length() - skipBytes ?
25 partSize : partFile.length() - skipBytes;
26
27 // Create UploadPartRequest to upload parts
28 UploadPartRequest uploadPartRequest = new UploadPartRequest();
29 uploadPartRequest.setBucketName(bucketName);
30 uploadPartRequest.setKey(objectKey);
31 uploadPartRequest.setUploadId(initiateMultipartUploadResponse.getUploadId());
32 uploadPartRequest.setInputStream(fis);
33 uploadPartRequest.setPartSize(size);
34 uploadPartRequest.setPartNumber(i + 1);
35 UploadPartResponse uploadPartResponse = client.uploadPart(uploadPartRequest);
36
37 // Save the returned PartETag to the List.
38 partETags.add(uploadPartResponse.getPartETag());
39
40 // Close the file
41 fis.close();
42}
The core of the above code is to call the UploadPart method to upload each part, but the following points should be noted:
- The uploadPart method requires that the size of each part, except the last one, must be greater than or equal to 100KB. However, the Upload Part interface does not immediately validate the Part size; validation occurs only during completing multipart upload.
- To ensure no errors during network transmission, it is recommended to use the Content-MD5 value returned by BOS for each part after
UploadPartto verify the correctness of the uploaded part data. When all part data is combined into one Object, it no longer contains the MD5 value. - The part number must be within the range of 1 to 10,000. If this limit is exceeded, BOS will return an InvalidArgument error code.
- For each uploaded part, the stream must be positioned at the beginning of the respective part.
- After each Part upload, the return result of BOS will include a
PartETagobject, which is a combination of the uploaded block's ETag and block number (PartNumber). It will be used in subsequent steps to complete the multipart upload, so it must be saved. Generally speaking, thesePartETagobjects will be saved in a List.
Complete multipart upload
Complete the multipart upload as shown in the following code:
1CompleteMultipartUploadRequest completeMultipartUploadRequest =
2 new CompleteMultipartUploadRequest(bucketName, objectKey, initiateMultipartUploadResponse.getUploadId(), partETags);
3
4 // Complete multipart upload
5CompleteMultipartUploadResponse completeMultipartUploadResponse =
6 client.completeMultipartUpload(completeMultipartUploadRequest);
7
8 // Print Object's ETag
9System.out.println(completeMultipartUploadResponse.getETag());
The partETags in the above code is the list of partETag saved in the second step. After BOS receives the part list submitted by the user, it will verify the validity of each data Part one by one. Once all data parts are validated, BOS will assemble the data parts into a complete Object.
Cancel multipart upload event
Users can cancel multipart uploads by using the abortMultipartUpload method.
1AbortMultipartUploadRequest abortMultipartUploadRequest =
2 new AbortMultipartUploadRequest(bucketName, objectKey, uploadId);
3
4 // Cancel multipart upload
5client.abortMultipartUpload(abortMultipartUploadRequest);
Retrieve unfinished multipart upload event
Users can obtain the unfinished multipart upload events in the bucket by the listMultipartUploads method.
1ListMultipartUploadsRequest listMultipartUploadsRequest =
2 new ListMultipartUploadsRequest(bucketName);
3 // Retrieve all upload events within the bucket
4ListMultipartUploadsResponse listing = client.listMultipartUploads(listMultipartUploadsRequest);
5
6 // Traverse all upload events
7for (MultipartUploadSummary multipartUpload : listing.getMultipartUploads()) {
8 System.out.println("Key: " + multipartUpload.getKey() + " UploadId: " + multipartUpload.getUploadId());
9}
Note:
- By default, if the number of multipart upload events in a bucket surpasses 1,000, only 1,000 records will be returned. In such cases, the IsTruncated value in the response will be True, and the NextKeyMarker will indicate the starting point for the next query.
- To retrieve more multipart upload events, you can utilize the KeyMarker parameter for batch reading.
Get all uploaded part information
Users can obtain all uploaded parts in an upload event by the listParts method.
1ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, objectKey, uploadId);
2
3 // Retrieve all uploaded part information
4ListPartsResponse partListing = client.listParts(listPartsRequest);
5
6 // Traverse all parts
7for (PartSummary part : partListing.getParts()) {
8 System.out.println("PartNumber: " + part.getPartNumber() + " ETag: " + part.getETag());
9}
If you need to view the storage class of an object, use the following code:
1public void listPartsStorageClass(){
2 ListResponse listPartsResponse = client.listParts(bucketName, key, uploadId);
3 String storageClass = listPartsResponse.getStorageClass();
4}
Note:
- By default, if the number of multipart upload events in a bucket surpasses 1,000, only 1,000 records will be returned. In such cases, the IsTruncated value in the response will be True, and the NextPartNumberMarker will indicate the starting point for the next query.
- To fetch additional multipart upload events, you can utilize the PartNumberMarker parameter for batch reading.
Encapsulate multipart upload
In the Java SDK, Bos provides users with the putSuperObjectFromFile API, which encapsulates the three methods involved in multipart upload: initiateMultipartUpload, UploadPart and completeMultipartUpload. Users only need to call this API to complete the multipart upload.
1File file = new File("/path/to/file.zip");
2PutSuperObjectRequest request = new PutSuperObjectRequest(bucketName, objectKey, file);
3bosClient.putSuperObjectFromFile(request);
The parameters of PutSuperObjectRequest include:
| Parameters | Description |
|---|---|
| chunkSize | Part size: The default is 5 MB, and it cannot be less than 100 KB |
| nThreads | Number of threads in the thread pool for multipart upload: The default is equal to the number of CPU cores |
| isSuperObjectUploadCanced | Cancel multipart upload or not |
| File | Upload files |
If uploading a large file takes too long and the user wishes to end the multipart upload, they can call the cancel() method in PutSuperObjectRequest to set isSuperObjectUploadCanceled to true, thereby canceling the multipart upload operation.
Resumable upload
When users upload large files to BOS, if the network is unstable or the program crashes, the entire upload will fail, and the parts that have been uploaded before the failure will also be invalid. Users have to start over. This not only wastes resources but also often fails to complete the upload after multiple retries in an unstable network environment. Based on the above scenarios, BOS provides the capability of resumable upload:
- In a generally stable network, it is recommended to use the three-step upload method, dividing the object into 5 MB blocks, refer to [Multipart Upload](#Multipart upload).
- If your network condition is very poor, it is recommended to use the appendObject method for resumable upload, appending small data (256 KB) each time, refer to [Append Upload](#Append upload).
Tips
- Resumable upload is an encapsulation and enhancement of multipart upload, implemented using multipart upload;
- For large files or poor network environments, it is recommended to use multipart upload;
Fetch and upload
The following code retrieves resources from a specified URL and stores them in a designated bucket. This process requires the requester to have write permissions for the bucket. Only one object can be fetched at a time, and the user can specify a custom object name. For details, refer to the FetchObject API.
1String fetchurl = "bj.bcebos.com/sourbucket/sourceobject";
2FetchObjectRequest req = new FetchObjectRequest(bucketname, objectname, fetchurl);
3bosClient.fetchObject(req);
Obtain upload progress
Supports providing real-time upload progress updates during the upload process. It currently supports four APIs: PutObject, AppendObject, UploadPart, and PutSuperObjectFromFile. The progress upload API accepts optional custom data.
The Java SDK defines upload progress callback APIs that allow users to define actions needed during upload, such as updating the API.
1public interface ProgressCallback<T> {
2 void onProgress(long currentSize, long totalSize, T data);
3}
- PutObject example code:
1BosProgressCallback<Object> callback = new BosProgressCallback<Object>() {
2 @Override
3 public void onProgress(long currentSize, long totalSize, Object data) {
4 System.out.println("put " + currentSize + "/" + totalSize);
5 }
6};
7 // If you need to use custom data in onProgress
8callback.setData(obj);
9PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, file);
10request.setProgressCallback(callback);
11client.putObject(request);
- AppendObject example code:
1BosProgressCallback<Object> callback = new BosProgressCallback<Object>() {
2 @Override
3 public void onProgress(long currentSize, long totalSize, Object data) {
4 System.out.println("put " + currentSize + "/" + totalSize);
5 }
6};
7 // If you need to use custom data in onProgress
8callback.setData(obj);
9AppendObjectRequest request = new AppendObjectRequest(bucketName, objectKey, file);
10request.setProgressCallback(callback);
11AppendObjectResponse response = client.appendObject(request);
12Long nextAppendOffset = response.getNextAppendOffset();
- UploadPart example code:
1BosProgressCallback<Object> callback = new BosProgressCallback<Object>() {
2 @Override
3 public void onProgress(long currentSize, long totalSize, Object data) {
4 System.out.println("put " + currentSize + "/" + totalSize);
5 }
6};
7 // If you need to use custom data in onProgress
8callback.setData(obj);
9UploadPartRequest request = new UploadPartRequest();
10request.setBucketName(bucketName);
11request.setKey(objectKey);
12request.setUploadId(id);
13request.setInputStream(inputStream);
14request.setPartSize(size);
15request.setPartNumber(i);
16request.setProgressCallback(callback);
17client.uploadPart((request);
- PutSuperObjectFromFile example code:
1BosProgressCallback<Object> callback = new BosProgressCallback<Object>() {
2 @Override
3 public void onProgress(long currentSize, long totalSize, Object data) {
4 System.out.println("put " + currentSize + "/" + totalSize);
5 }
6};
7 // If you need to use custom data in onProgress
8callback.setData(obj);
9PutSuperObjectRequest request = new PutSuperObjectRequest(bucketName, objectKey, file);
10request.setProgressCallback(callback);
11client.putSuperObjectFromFile(request);
Download file
The BOS Java SDK provides a variety of file download APIs, allowing users to download files from BOS in the following ways:
- Simple streaming download
- Download to a local file
- Resumable download
- Range download
- Download progress bar
For the complete sample code, please refer to File Download Demo
Simple streaming download
Users can read the object into a stream using the following code:
1public void getObject(BosClient client, String bucketName, String objectKey)
2 throws IOException {
3 //Obtain the object, with returned result BosObject object
4 BosObject object = client.getObject(bucketName, objectKey);
5 // Retrieve ObjectMeta
6 ObjectMetadata meta = object.getObjectMetadata();
7 //Obtain the object's input stream
8 InputStream objectContent = object.getObjectContent();
9 // Process object
10 ...
11 // Close stream
12 objectContent.close();
13}
Note:
- The BosObject includes various details about the object, such as the bucket it belongs to, the object’s name, metadata, and an input stream. Users can read the object's content into a file or memory by interacting with the input stream.
- ObjectMetadata contains information such as the ETag defined during object upload, HTTP headers, and custom metadata.
- Users can also use the getObjectContent method of BosObject to obtain the input stream of the returned object, enabling operations on the object's content.
Directly download an object to a file
Users can directly download an object to the specified file using the following code:
1// Create GetObjectRequest
2GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectKey);
3
4 // Download object to file
5ObjectMetadata objectMetadata = client.getObject(getObjectRequest, new File("/path/to/file","filename"));
When downloading an object directly to a specified file using the mentioned method, the method returns an ObjectMetadata object.
Range download
To implement more functions, you can use GetObjectRequest to specify the download range for more refined acquisition of the object. If the specified download range is 0-100, it will return data from byte 0 to byte 100, including byte 100, with a total of 101 bytes of data, i.e., [0, 100].
1// Create GetObjectRequest
2GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectKey);
3 // Obtain data within the 0~100 byte range
4getObjectRequest.setRange(0, 100);
5 //Obtain the object, with returned result BosObject object
6BosObject object = client.getObject(getObjectRequest);
The range of the returned object can be configured using the setRange method of the getObjectRequest. This allows users to perform segmented downloads and resumable uploads of files.
Download the image-processed file
The Java SDK supports image processing while downloading files. You only need to set the x-bce-process parameter in the request. For the usage of specific parameters, please refer to Image Processing. Example code is as follows:
1// Create GetObjectRequest
2GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectKey);
3 // Set image processing to zoom
4getObjectRequest.setxBceProcess("image/resize,m_fixed,w_200,h_100");
5 // Get the object, with the processed BosObject returned
6BosObject object = client.getObject(getObjectRequest);
Other methods
Get the storage class of the object
The storage class attributes of an object are divided into STANDARD (standard storage), STANDARD_IA (infrequent access storage), and COLD (cold storage). This can be achieved through the following code:
1public void getObjectStorageClass(){
2 ObjectMetadata meta = client.getObjectMetadata(bucketName, key);
3 String storageClass = meta.getStorageClass();
4}
Get only ObjectMetadata
The getObjectMetadata method is designed to retrieve only the ObjectMetadata, not the object itself. This can be demonstrated in the following code:
1ObjectMetadata objectMetadata = client.getObjectMetadata(bucketName, objectKey);
The parameters available for calling in the getObjectMetadata parsing class are:
| Parameters | Description |
|---|---|
| contentType | Object type |
| contentLength | Object size |
| contentMd5 | Object MD5 |
| etag | The HTTP protocol entity tag of object |
| storageClass | Storage class of the object |
| userMetadata | If userMetadata custom meta is specified in PutObject, this item will be returned |
| xBceCrc | If the CRC value (Cyclic Redundancy Check code) of the object is specified in PutObject, this item will be returned |
Restore archived storage class files
Restore archived class files
When a user uploads an archived file, it enters a frozen state. To download it, the archived file must first be restored. The requester must have read permissions for the archived file, and the file must remain in its frozen state.
Examples of restoring archived files are as follows:
1RestoreObjectRequest request = new RestoreObjectRequest(bucketName, objectKey);
2request.setRestoreDays(10);
3 // Expedited restoration (RESTORE_TIER_EXPEDITED), standard restoration (RESTORE_TIER_STANDARD), deferred restoration (RESTORE_TIER_LOWCOST)
4request.setRestoreTier(RESTORE_TIER_EXPEDITED);
5client.restoreObject(request);
| Parameters | Types | Description | Required or not |
|---|---|---|---|
| days | int | Defines the duration of the restored state in days, with a numeric value greater than 0 and less than 30. By default, the restoration duration is 7 days, with a maximum duration of 30 days. | No |
| tier | string | Restore priority. The available values are as follows:
|
No |
Change file storage class
As mentioned above, BOS supports three storage classes for files: STANDARD (standard storage), STANDARD_IA (infrequent access storage), and COLD (cold storage). Meanwhile, the BOS java SDK also allows users to perform operations to change the storage class of specific files. The relevant parameters are as follows:
| Parameters | Description |
|---|---|
| x-bce-storage-class | Define the object's storage class. STANDARD_IA indicates infrequent access storage, COLD indicates cold storage, and if no class is specified, the default is standard storage. |
An example is as follows:
1// Convert standard storage to infrequent access storage
2CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
3copyObjectRequest.setStorageClass("STANDARD_IA");
4client.copyObject(copyObjectRequest);
5 // Convert infrequent access storage to cold storage
6CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
7copyObjectRequest.setStorageClass("COLD");
8client.copyObject(copyObjectRequest);
Get file download URL
Users can obtain the URL of a specified object through the following code:
1public String generatePresignedUrl(BosClient client, String bucketName, String objectKey, int expirationInSeconds) {
2 URL url = client.generatePresignedUrl(<bucketName>, <objectKey>, <expirationInSeconds>);
3 //Specify the name of the bucket where the object that the user needs to get is located, the name of the object, timestamp and the valid duration of the URL
4 return url.toString();
5}
Description:
- Before calling this function, users need to manually set the endpoint to the domain name of the corresponding region. Baidu AI Cloud currently supports multiple regions. Please refer to[Region Selection Guide](Reference/Region Selection Instructions/Region.md). Currently, the supported regions include "North China-Beijing," "South China-Guangzhou" and "East China-Suzhou." Beijing region:
http://bj.bcebos.com, Guangzhou region:http://gz.bcebos.com, Suzhou region:http://su.bcebos.com.expirationInSecondsis the specified URL validity period, calculated from the current time. It is an optional parameter, and the system default value is 1,800 seconds if not configured. To set a permanent non-expiration time, theExpirationInSecondsparameter can be set to -1. You cannot set it to any other negative value.- If the file to be obtained is expected to be publicly readable, the corresponding URL link can be quickly concatenated and obtained through simple rules:
http://$bucketName.$region.bcebos.com/$objectKeyorhttp://$region.bcebos.com/$bucketName/$objectKey
List files in the storage space
The BOS SDK allows users to list objects in the following two ways:
- Simple listing
- Advanced listing via parameters
In addition, users can also simulate folders while listing files. For the complete sample code, please refer to File Listing Demo
Simple listing
To quickly and easily list the needed files, users can use the listObjects method, which returns a ListObjectsResponse object containing the results of the listObject request. Users can retrieve details of all objects using the getContents method in the ListObjectsResponse.
1public void listObjects(BosClient client, String bucketName) {
2 // Obtain all object information under the specified bucket
3 ListObjectsResponse listing = client.listObjects(bucketName);
4 // Traverse all objects
5 for (BosObjectSummary objectSummary : listing.getContents()) {
6 System.out.println("ObjectKey: " + objectSummary.getKey());
7 }
8}
Note:
- By default, if the number of objects in the bucket exceeds 1,000, only 1,000 objects will be returned. In this case, the IsTruncated value in the returned result will be set to True, and NextMarker will be provided as the starting point for the next retrieval.
- To retrieve more objects, the marker parameter can be used to enable batch reading.
Advanced listing via parameters
In addition to simple listing, users can achieve various flexible queries by adjusting the parameters of ListObjectsRequest. The available parameters for ListObjectsRequest include:
| Parameters | Function | Usage method |
|---|---|---|
| Prefix | Restrict the returned object keys to those starting with a specific prefix | setPrefix(String prefix) |
| Delimiter | A character used to group object names. Only objects containing the specified prefix and appearing for the first time are included. Objects between the delimiter characters are treated as a single group element: CommonPrefixes. | setDelimiter(String delimiter) |
| Marker | Set the result to start returning from the first object in alphabetical order after the marker | setMarker(String marker) |
| MaxKeys | Set the maximum number of objects to return, with a default and upper limit of 1,000. Specifying a value greater than 1,000 will default to 1,000. | setMaxKeys(int maxKeys) |
Note:
- If there is an object named with the prefix, querying only by prefix will return all keys, including the object with the prefix.
- If there is an object named with the prefix, querying with both a prefix and a delimiter will result in Null for all returned keys, and the key names will not include the prefix.
The following are several examples to illustrate the method of listing via parameters:
Specify the maximum number of returned items
1//Specify the maximum number of returned items as 500
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest("bucketName");
3listObjectsRequest.withMaxKeys(500);
4ListObjectsResponse listObjectsResponse = client.listObjects(listObjectsRequest);
5for(BosObjectSummary objectSummary :listObjectsResponse.getContents()) {
6 System.out.println("ObjectKey:" + objectSummary.getKey());
7}
Return objects with a specified prefix
1//Specify to return objects with the prefix “test"
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest("bucketName");
3listObjectsRequest.withPrefix("test");
4ListObjectsResponse listObjectsResponse = client.listObjects(listObjectsRequest);
5for(BosObjectSummary objectSummary :listObjectsResponse.getContents()) {
6 System.out.println("ObjectKey:" + objectSummary.getKey());
7}
Return from after a specified object
1//Users can define to exclude a certain object and start returning from after it
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest("bucketName");
3listObjectsRequest.withMarker("object");
4ListObjectsResponse listObjectsResponse = client.listObjects(listObjectsRequest);
5for(BosObjectSummary objectSummary :listObjectsResponse.getContents()) {
6 System.out.println("ObjectKey:" + objectSummary.getKey());
7}
Pagination to get all objects
1//Users can set a maximum of 500 records per page
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest("bucketName");
3listObjectsRequest.withMaxKeys(500);
4ListObjectsResponse listObjectsResponse;
5boolean isTruncated = true;
6while (isTruncated) {
7 listObjectsResponse = client.listObjects(listObjectsRequest);
8 isTruncated = listObjectsResponse.isTruncated();
9 if (listObjectsResponse.getNextMarker() != null) {
10 listObjectsRequest.withMarker(listObjectsResponse.getNextMarker());
11 }
12}
Results of paginated restoration of all objects after a specific object
1//Users can set a maximum of 500 records per page and start getting from after a specific object
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest("bucketName");
3listObjectsRequest.withMaxKeys(500);
4listObjectsRequest.withMarker("object");
5ListObjectsResponse listObjectsResponse;
6boolean isTruncated = true;
7while (isTruncated) {
8 listObjectsResponse = client.listObjects(listObjectsRequest);
9 isTruncated = listObjectsResponse.isTruncated();
10 if (listObjectsResponse.getNextMarker() != null) {
11 listObjectsRequest.withMarker(listObjectsResponse.getNextMarker());
12 }
13}
Results of paginated restoration of all objects after a specific object
1//Users can set pagination to get objects with a specified prefix, with a maximum of 500 records per page
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest("bucketName");
3listObjectsRequest.withMaxKeys(500);
4listObjectsRequest.withPrefix("object");
5ListObjectsResponse listObjectsResponse;
6boolean isTruncated = true;
7while (isTruncated) {
8 listObjectsResponse = client.listObjects(listObjectsRequest);
9 isTruncated = listObjectsResponse.isTruncated();
10 if (listObjectsResponse.getNextMarker() != null) {
11 listObjectsRequest.withMarker(listObjectsResponse.getNextMarker());
12 }
13}
The parameters available for calling in the resolution class returned by the listObject method are as follows:
| Parameters | Description |
|---|---|
| name | Bucket name |
| prefix | The matched objects from prefix to the first Delimiter character are returned as a group of elements |
| marker | Starting point of this query |
| maxKeys | Maximum number of requests returned |
| isTruncated | Indicate whether all queries are returned; false - all results are returned this time; true - not all results are returned this time |
| contents | A container for the returned objects |
| +key | Object name |
| +lastModified | Last modification time of the object |
| +eTag | The HTTP protocol entity tag of object. |
| +storageClass | Storage class of object |
| +size | The size of the object content (in bytes) |
| +owner | User information of the bucket corresponding to the object |
| ++id | User ID of bucket owner |
| ++displayName | Name of bucket owner |
Simulate folder function
In BOS storage, there is no concept of folders. All elements are stored as objects. However, when using data, BOS users often need to manage files in folders. Therefore, BOS provides the ability to create simulated folders, which essentially involves creating an object with a size of 0. This object can be uploaded and downloaded, but the console will display objects ending with “/” as folders.
By combining the delimiter and prefix parameters, users can simulate folder functionalities. The combined effect of delimiter and prefix is as follows:
If prefix is set to a folder name, files starting with the prefix can be listed, including all files and subfolders (directory) recursively listed under the folder. File names are displayed in contents. If delimiter is set to /, the return values only list the files and subfolders (directory) under the folder. The names of subfolders (directory) under the folder are returned in the CommonPrefixes. The files and folders recursively listed under the subfolders are not displayed.
The following are several application methods:
List all files in the bucket
When users need to get all files under a bucket, they can refer to [Pagination to Get All Objects](#Advanced listing via parameters)
Recursively list all files in a directory
You can obtain all files in the a directory by setting the Prefix parameter:
1// Construct a ListObjectsRequest request
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
3
4 // Recursively list all files under the fun directory
5listObjectsRequest.setPrefix("fun/");
6
7ListObjectsResponse listing = client.listObjects(listObjectsRequest);
8
9 // Traverse all objects
10System.out.println("Objects:");
11for (BosObjectSummary objectSummary : listing.getContents()) {
12 System.out.println(objectSummary.getKey());
13 }
14}
Output:
1Objects:
2fun/
3fun/movie/001.avi
4fun/movie/007.avi
5fun/test.jpg
View files and subdirectories in a directory
With the combination of Prefix and Delimiter, it can list files and subdirectories under the directory:
1// Construct a ListObjectsRequest request
2ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
3
4 // "/" is the delimiter for folders
5listObjectsRequest.setDelimiter("/");
6
7 //List all files and folders under the “fun” directory
8listObjectsRequest.setPrefix("fun/");
9
10ListObjectsResponse listing = client.listObjects(listObjectsRequest);
11
12 // Traverse all objects
13System.out.println("Objects:");
14for (BosObjectSummary objectSummary : listing.getContents()) {
15 System.out.println(objectSummary.getKey());
16}
17
18 // Traverse all CommonPrefix
19System.out.println("\nCommonPrefixs:");
20for (String commonPrefix : listing.getCommonPrefixes()) {
21 System.out.println(commonPrefix);
22}
Output:
1Objects:
2fun/
3fun/test.jpg
4
5CommonPrefixs:
6fun/movie/
In the returned results, the list in ObjectSummaries shows the files under the fun directory. The list in CommonPrefixs shows all subfolders under the fun directory. It can be seen that the two files fun/movie/001.avi and fun/movie/007.avi are not listed because they belong to the movie directory under the fun folder.
List storage properties of objects in a bucket
After users complete the upload, if they need to view the storage class properties of all objects in a specified bucket, it can be achieved through the following code:
1public void listObjectsStorageClass(){
2 ListObjectsResponse listObjectResponse = client.listObjects("bucketName");
3 List<BosObjectSummary> objectList = listObjectResponse.getContents();
4 for(int i=0; i<objectList.length(); i++) {
5 System.out.println(objectList[i].getStorageClass());
6 }
7}
Get directory capacity overview
Users can get the current capacity, number of objects, and number of files under a bucket or a specified prefix through the following code. Here, the term “file” refers to ordinary files, excluding folders, let alone directories in the logical sense of delimiters. An “object” is the number of keys actually stored in the bucket. That is, the number of files is equal to the number of objects minus the number of objects ending with a delimiter. For example, if there are 9 objects in the current directory, 5 of which are folders and 4 are files, then the number of files found is 4, and the number of objects is 9.
1public void stateSummary(BosClient client, String bucketName, String prefix) {
2 // Get the current capacity, number of objects, and number of files under the bucket
3 StateSummaryResponse response = client.stateSummary(bucketName);
4 System.out.println("currSize : " + response.getTotalSize());
5 System.out.println("objectsCount : " + response.getObjectsCount());
6 System.out.println("filesCount : " + response.getFilesCount());
7}
Get the capacity, number of objects, and number of files of objects with a specified prefix:
1public StateSummaryResponse stateSummaryWithPrefix(BosClient client, String bucketName, String prefix) {
2 StateSummaryRequest request = new StateSummaryRequest();
3 request.setBucketName(this.bucketName);
4 request.setPrefix("dir/x");
5 StateSummaryResponse response = client.stateSummary(request);
6 return response;
7}
Object permission control
Set access permission for an object.
Currently, BOS supports two methods for setting ACLs. The first method is to use Canned ACL. During PutObjectAcl, the object access permission is set via the header "x-bce-acl" or "x-bce-grant-permission". Currently configurable permissions include private and public-read. The two types of headers cannot appear in the same request simultaneously. The second method is to upload an ACL file.
For detailed information, please refer to Setting Object Access Control, or check Demo Examples.
- Set object access permission using the headers "x-bce-acl" or "x-bce-grant-permission"
- set object acl First method (Set via request headers)
1SetObjectAclRequest setObjectAclRequest = new SetObjectAclRequest("yourBucketName","objectKey",CannedAccessControlList.PublicRead);
2client.setObjectAcl(setObjectAclRequest);
- set object acl First method (Set xBceGrantRead via request headers)
1String xBceGrantRead = "id=\"user_id1\""+",id=\"user_id2\"";
2SetObjectAclRequest setObjectAclRequest = new SetObjectAclRequest();
3setObjectAclRequest.withBucketName("yourBucketName");
4setObjectAclRequest.withKey("objectKey");
5setObjectAclRequest.setxBceGrantRead(xBceGrantRead);
6client.setObjectAcl(setObjectAclRequest);
- set object acl First method (Set xBceGrantFullControl via request headers)
1String xBceGrantFullControl = "id=\"user_id1\""+",id=\"user_id2\"";
2SetObjectAclRequest setObjectAclRequest = new SetObjectAclRequest();
3setObjectAclRequest.withBucketName("yourBucketName");
4setObjectAclRequest.withKey("objectKey");
5setObjectAclRequest.setxBceGrantFullControl(xBceGrantFullControl);
6client.setObjectAcl(setObjectAclRequest);
- Set object access permission via setObjectAcl
- set object acl Second Method (JSON string)
1String jsonObjectAcl = "{\"accessControlList\":["+ "{\"grantee\":[{\"id\":\"*\"}], "+ "\"permission\":[\"FULL_CONTROL\"]"+"}]}";
2SetObjectAclRequest setObjectAclRequest = new SetObjectAclRequest("yourBucketName","objectKey",jsonObjectAcl);
3client.setObjectAcl(setObjectAclRequest);
- set object acl Second Method, by which users only need to specify the specified parameters
1List<Grant> grants = new ArrayList<Grant>();
2List<Grantee> grantees = new ArrayList<Grantee>();
3List<Permission> permissions = new ArrayList<Permission>();
4 // Grant permission to specific user
5grantees.add(new Grantee("user_id1"));
6grantees.add(new Grantee("user_id2"));
7grantees.add(new Grantee("user_id3"));
8 // Set permissions
9permissions.add(Permission.READ);
10grants.add(new Grant().withGrantee(grantees).withPermission(permissions));
11SetObjectAclRequest setObjectAclRequest = new SetObjectAclRequest("yourBucketName","objectKey", grants);
12client.setObjectAcl(setObjectAclRequest);
View object permissions
The following code can be used to check the object permissions:
1GetObjectAclRequest getObjectRequest = new GetObjectAclRequest();
2getObjectRequest.withBucketName("yourBucketName");
3getObjectRequest.withKey("objectKey");
4GetObjectAclResponse response = client.getObjectAcl(getObjectRequest);
The parameters available for calling in the resolution class returned by the getObjectAcl method are as follows:
| Parameters | Description |
|---|---|
| accessControlList | Identify the permission list of the object |
| grantee | Identify the grantee |
| -id | Authorized person ID |
| permission | Identify the grantee permissions |
Delete object permissions
The following code can be used to delete the object permissions:
1DeleteObjectAclRequest deleteObjectAclRequest = new DeleteObjectAclRequest("yourBucketName","objectKey");
2client.deleteObjectAcl(deleteObjectAclRequest);
Delete file
For the sample code, please refer to File Deletion Demo
Delete single file
The following code can be referenced to delete an object:
1public void deleteObject(BosClient client, String bucketName, String objectKey) {
2 // Delete Object
3 client.deleteObject(<BucketName>, <ObjectKey>); //Specify the name of the bucket where the object to be deleted is located and the name of the object
4}
Delete multiple files
Delete multiple files
You can refer to the following two methods to delete multiple objects:
1// 1. In the form of a Json string
2String jsonObjectKeys = "{\"objects\": ["+"{\"key\": \"token1.h\"},"+"{\"key\": \"token2.h\"}"+"]}";
3DeleteMultipleObjectsRequest request = new DeleteMultipleObjectsRequest();
4request.setBucketName("yourBucketName");
5request.setJsonDeleteObjects(jsonObjectKeys);
6client.deleteMultipleObjects(request);
1// 2. Users only need to specify the parameters
2List<String> objectKeys = new ArrayList<String>();
3objectKeys.add("object1");
4objectKeys.add("object2");
5DeleteMultipleObjectsRequest request = new DeleteMultipleObjectsRequest();
6request.setBucketName("yourBucketName");
7request.setObjectKeys(objectKeys);
8DeleteMultipleObjectsResponse response = client.deleteMultipleObjects(request);
1,000 objects can be deleted at most via a single request. The message body (body) does not exceed 2 M. The returned message body only includes erroneous object results in the deletion process; no message body is returned if all objects are deleted successfully.
Check if a file exists
Users can check if a file exists through the following operations:
1// Returns true if it exists, false if it does not exist, and other exceptions will be thrown
2bool exists = client.doesObjectExist("bucketName", "objectKey");
Get and update file meta information
File metadata, or object metadata, describes the attributes of files uploaded to BOS. It includes two types: HTTP standard attributes (HTTP headers) and user-defined metadata.
Get file meta information
Refer to [Retrieve Only ObjectMetadata](#Other methods), or Demo
Modify file meta information
BOS modifies object metadata by copying the object. When copying, set the destination bucket and object as the source bucket and object, then apply the new metadata. If new metadata is not specified, an error will occur.
1 public void setObjectMeta(BosClient client, String bucketName, String objectKey, ObjectMetadata newObjectMetadata) {
2
3 CopyObjectRequest request = new CopyObjectRequest(bucketName, objectKey, bucketName, objectKey);
4 //Set new ObjectMetadata
5 request.setNewObjectMetadata(newObjectMetadata);
6 // Copy Object
7 CopyObjectResponse copyObjectResponse = client.copyObject(request);
8 // Print results
9 System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
10 }
Copy files
For the sample code, please refer to File Copy Demo
Copy a file
Users can copy an object using the copyObject method, as shown in the following code:
1public void copyObject(BosClient client, String srcBucketName, String srcKey, String destBucketName, String destKey) {
2
3 // Copy Object
4 CopyObjectResponse copyObjectResponse = client.copyObject(srcBucketName, srcKey, destBucketName, destKey);
5
6 // Print results
7 System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
8}
The copyObject method returns a CopyObjectResponse object containing the new object's ETag and modification time.
Copy Object via CopyObjectRequest
Users can also copy object via CopyObjectRequest. the code is as follows:
1// Initialize BosClient
2BosClient client = ...;
3
4 // Create CopyObjectRequest object
5CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
6
7 // Set new Metadata
8Map<String, String> userMetadata = new HashMap<String, String>();
9userMetadata.put('<user-meta-key>','<user-meta-value>');
10ObjectMetadata meta = new ObjectMetadata();
11meta.setUserMetadata(userMetadata);
12copyObjectRequest.setNewObjectMetadata(meta);
13
14 // Copy Object
15CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
16
17System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
CopyObjectRequest allows users to modify the ObjectMeta of the target object and also provides the setting of the MatchingETagConstraints parameter.
Set the copy attribute of the object
BOS provides a CopyObject API for copying an existing object to a different object. During the copying process, it evaluates the source object’s ETag or modification status to determine whether to proceed. Detailed parameter descriptions are as follows:
| Name | Types | Description | Whether required |
|---|---|---|---|
| x-bce-copy-source-if-match | String | If the ETag value of the source object matches the ETag value provided by the user, the copy operation is performed; otherwise, it fails. | No |
| x-bce-copy-source-if-none-match | String | If the ETag value of the source object does not match the ETag value provided by the user, the copy operation is performed; otherwise, it fails. | No |
| x-bce-copy-source-if-unmodified-since | String | If the source object has not been modified since x-bce-copy-source-if-unmodified-since, the copy operation will proceed; otherwise, it will fail. | No |
| x-bce-copy-source-if-modified-since | String | If the source object has been modified since x-bce-copy-source-if-modified-since, the copy operation will proceed; otherwise, it will fail. | No |
The corresponding example code:
1// Initialize BosClient
2BosClient client = ...;
3 // Create CopyObjectRequest object
4CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
5 // Set new Metadata
6Map<String, String> userMetadata = new HashMap<String, String>();
7userMetadata.put("<user-meta-key>","<user-meta-value>");
8
9meta.setUserMetadata(userMetadata);
10copyObjectRequest.setNewObjectMetadata(meta);
11//copy-source-if-match
12copyObjectRequest.withETag("111111111183bf192b57a4afc76fa632");
13//copy-source-if-none-match
14copyObjectRequest.withNoMatchingETagConstraint("111111111183bf192b57a4afc76fa632");
15
16Date modifiedSinceConstraint = new Date();
17SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
18df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
19String date = df.format(modifiedSinceConstraint);
20//copy-source-if-modified-since
21copyObjectRequest.withModifiedSinceConstraint(date);
22//copy-source-if-unmodified-since
23copyObjectRequest.withUnmodifiedSinceConstraint(date);
24 // Copy Object
25CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
26System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
Synchronous copy function
Currently, BOS’s CopyObject API operates in a synchronous manner. This means BOS waits until the copy operation is fully completed before returning a success status. While synchronous copying provides a more accurate status for users, it also takes longer and is proportional to the file size.
The synchronous copy approach aligns better with industry standards and improves compatibility with other platforms. It also simplifies the server’s business logic and enhances service efficiency.
If you are using an SDK version earlier than bce-java-sdk-0.10.8, you might encounter scenarios where the copy request succeeds but the actual file copy fails. It is therefore recommended to use the latest version of the SDK.
Multipart copy
Apart from using the CopyObject API for copying, BOS offers another method—Multipart Upload Copy. This method is suitable for the following application scenarios (but not limited to these):
- When a resumable copy process is required.
- For copying files larger than 5GB.
- When the connection to the BOS server frequently disconnects due to poor network conditions.
The following section introduces the step-by-step process for implementing the three-step copy method.
The three-step copy process includes three stages: initialization ("init"), "copy part," and completion. The initialization and completion steps are the same as those for multipart uploads.
For easier understanding, the complete code for three-step copy is provided below:
1//Step I: init
2InitiateMultipartUploadRequest initiateMultipartUploadRequest =
3 new InitiateMultipartUploadRequest("targetBucketName","targetObjectName");
4InitiateMultipartUploadResponse initiateMultipartUploadResponse =
5 client.initiateMultipartUpload(initiateMultipartUploadRequest);
6 //Step II: Multipart copy
7long left_size=client.getObjectMetadata("sourceBucketName","sourceObjectName").getContentLength();
8long skipBytes = 0;
9int partNumber = 1;
10List<PartETag> partETags = new ArrayList<PartETag>();
11while (left_size > 0) {
12 long partSize = 1024 * 1024 * 1L;
13 if (left_size < partSize) {
14 partSize = left_size;
15 }
16 UploadPartCopyRequest uploadPartCopyRequest = new UploadPartCopyRequest();
17 uploadPartCopyRequest.setBucketName("targetBucketName");
18 uploadPartCopyRequest.setKey("targetObjectName");
19 uploadPartCopyRequest.setSourceBucketName("sourceBucketName");
20 uploadPartCopyRequest.setSourceKey("sourceObjectName");
21 uploadPartCopyRequest.setUploadId(initiateMultipartUploadResponse.getUploadId());
22 uploadPartCopyRequest.setPartSize(partSize);
23 uploadPartCopyRequest.setOffSet(skipBytes);
24 uploadPartCopyRequest.setPartNumber(partNumber);
25 UploadPartCopyResponse uploadPartCopyResponse = client.uploadPartCopy(uploadPartCopyRequest);
26 // Save the returned PartETag to the list
27 PartETag partETag = new PartETag(partNumber,uploadPartCopyResponse.getETag());
28 partETags.add(partETag);
29 left_size -= partSize;
30 skipBytes += partSize;
31 partNumber+=1;
32}
33 //Step III: complete
34CompleteMultipartUploadRequest completeMultipartUploadRequest =
35 new CompleteMultipartUploadRequest("targetBucketName", "targetObjectName", initiateMultipartUploadResponse.getUploadId(), partETags);
36CompleteMultipartUploadResponse completeMultipartUploadResponse =
37 client.completeMultipartUpload(completeMultipartUploadRequest);
Note:
- The offset parameter is specified in bytes and represents the starting position of the part within the file.
- The size parameter is in bytes and defines the size of each part. Except for the last part, the size of other Parts must be larger than 5MB。
Select file
The BOS Java SDK provides the SelectObject API, which is used to execute SQL statements on specified objects in the bucket and return the selected content. Please refer to [Select Object](BOS/API Reference/Object-Related Interface/Select scanning/SelectObject.md). Currently, supported object types are CSV (including TSV and other CSV-like files) and JSON files:
For the sample code, please refer to File Selection Demo
- Select CSV files
- Select JSON files
Select CSV files
For selecting CSV files with the Java SDK, please refer to the following code:
1final String csvContent = "header1,header2,header3\r\n" +
2 "1,2,3.4\r\n" +
3 "a,b,c\r\n" +
4 "\"d\",\"e\",\"f\"\r\n" +
5 "true,false,true\r\n" +
6 "2006-01-02 15:04:06,2006-01-02 16:04:06,2006-01-02 17:04:06";
7client.putObject("bucketName", "test-csv", new ByteArrayInputStream(csvContent.getBytes()));
8SelectObjectRequest request = new SelectObjectRequest("bucketName", "test-csv")
9 .withSelectType("csv")
10 .withExpression("select * from BosObject limit 3")
11 .withInputSerialization(new InputSerialization()
12 .withCompressionType("NONE")
13 .withFileHeaderInfo("NONE")
14 .withRecordDelimiter("\r\n")
15 .withFieldDelimiter(",")
16 .withQuoteCharacter("\"")
17 .withCommentCharacter("#"))
18 .withOutputSerialization(new OutputSerialization()
19 .withOutputHeader(false)
20 .withQuoteFields("ALWAYS")
21 .withRecordDelimiter("\n")
22 .withFieldDelimiter(",")
23 .withQuoteCharacter("\""))
24 .withRequestProgress(false);
25SelectObjectResponse response = client.selectObject(request);
26 // Output the returned records
27SelectObjectResponse.Messages messages = response.getMessages();
28while (messages.hasNext()) {
29 SelectObjectResponse.CommonMessage message = messages.next();
30 if (message.Type.equals("Records")) {
31 for (String record: message.getRecords()) {
32 System.out.println(record);
33 }
34 }
35}
Results of selecting CSV files:
1"header1","header2","header3"
2"1","2","3.4"
3"a","b","c"
Note:
- In Unix/Linux systems, each line ends with only a "
", i.e., "\n"; - In Windows systems, each line ends with a "
", i.e., "\r\n"; - In Mac systems, each line ends with a "
", i.e., "". Only Mac OS before version 9 uses '\r'. - Set the recordDelimiter appropriately based on the file content.
Select JSON files
For selecting JSON files with the Java SDK, please refer to the following code:
1final String jsonContent = "{\n" +
2 "\t\"name\": \"Smith\",\n" +
3 "\t\"age\": 16,\n" +
4 "\t\"org\": null\n" +
5 "}\n" +
6 "{\n" +
7 "\t\"name\": \"charles\",\n" +
8 "\t\"age\": 27,\n" +
9 "\t\"org\": \"baidu\"\n" +
10 "}\n" +
11 "{\n" +
12 "\t\"name\": \"jack\",\n" +
13 "\t\"age\": 35,\n" +
14 "\t\"org\": \"bos\"\n" +
15 "}";
16client.putObject("bucketName", "test-json", new ByteArrayInputStream(jsonContent.getBytes()));
17SelectObjectRequest request = new SelectObjectRequest("bucketName", "test-json")
18 .withSelectType("json")
19 .withExpression("select * from BosObject where age > 20")
20 .withInputSerialization(new InputSerialization()
21 .withCompressionType("NONE")
22 .withJsonType("LINES"))
23 .withOutputSerialization(new OutputSerialization()
24 .withRecordDelimiter("\n"))
25 .withRequestProgress(false);
26SelectObjectResponse response = client.selectObject(request);
27 // Output the returned records
28SelectObjectResponse.Messages messages = response.getMessages();
29while (messages.hasNext()) {
30 SelectObjectResponse.CommonMessage message = messages.next();
31 if (message.Type.equals("Records")) {
32 for (String record: message.getRecords()) {
33 System.out.println(record);
34 }
35 }
36}
Results of selecting JSON files:
1{"name":"charles","age":27,"org":"baidu"}
2{"name":"jack","age":35,"org":"bos"}
Note that when querying CSV and JSON files, the parameters for initializing SelectObjectRequest differ significantly. For detailed parameter settings, please refer to [SelectObject API](BOS/API Reference/Object-Related Interface/Select scanning/SelectObject.md).
