如何通过jclouds Java SDK实现OpenStack Swift分片上传并配置元数据
Hey, great question! I’ve run into this exact issue before—jclouds doesn’t expose a dedicated Swift-specific multipart upload API out of the box, but you absolutely can implement it using the framework’s underlying interfaces, and still use PutOptions to attach metadata as you need.
OpenStack Swift uses Large Objects (split into Static and Dynamic variants) to handle large file uploads. Static Large Objects are the most straightforward for controlled multipart uploads, so we’ll focus on that approach here.
Step 1: Get the Swift BlobStore/Api Instance
First, initialize your jclouds context to interact with Swift:
// Initialize the BlobStore context for OpenStack Swift BlobStoreContext context = ContextBuilder.newBuilder("openstack-swift") .endpoint("YOUR_SWIFT_AUTH_ENDPOINT") .credentials("YOUR_USERNAME", "YOUR_PASSWORD") .buildView(BlobStoreContext.class); // Get the BlobStore (or unwrap to SwiftApi for lower-level control) BlobStore blobStore = context.getBlobStore(); SwiftApi swiftApi = context.unwrapApi(SwiftApi.class);
Step 2: Upload Individual Parts with Metadata
Treat each file chunk as a regular Swift object, and use PutOptions to add metadata to each part (if needed):
String containerName = "your-target-container"; String largeObjectName = "my-large-file.bin"; String partPrefix = largeObjectName + "-part-"; // Example: Upload 3 chunks for (int partNum = 0; partNum < 3; partNum++) { String partName = partPrefix + partNum; File partFile = new File("/path/to/your-chunk-" + partNum); // Build the part blob Blob partBlob = blobStore.blobBuilder(partName) .payload(partFile) .build(); // Configure PutOptions with part-specific metadata PutOptions partOptions = new PutOptions(); partOptions.addMetadata("x-object-meta-part-number", String.valueOf(partNum)); partOptions.addMetadata("x-object-meta-content-type", "application/octet-stream"); // Upload the part blobStore.putBlob(containerName, partBlob, partOptions); }
Step 3: Create & Upload the Manifest File (Combine Parts)
The final step is to upload a manifest file that tells Swift to combine your parts into a single large object. Here’s where you’ll use PutOptions to set metadata for the final large object:
// Build the manifest content (each line is the path to a part) StringBuilder manifestContent = new StringBuilder(); for (int partNum = 0; partNum < 3; partNum++) { manifestContent.append("/").append(containerName).append("/").append(partPrefix).append(partNum).append("\n"); } // Build the manifest blob Blob manifestBlob = blobStore.blobBuilder(largeObjectName) .payload(manifestContent.toString()) .contentType("text/plain") // Required for Swift manifest files .build(); // Configure PutOptions for the final large object PutOptions manifestOptions = new PutOptions(); // Add custom metadata manifestOptions.addMetadata("x-object-meta-original-filename", "my-large-file.bin"); manifestOptions.addMetadata("x-object-meta-uploaded-by", "jclouds-user"); // Add standard HTTP headers (like Content-Type for the final object) manifestOptions.addHeader("Content-Type", "application/octet-stream"); // Critical: Tell Swift this is a static large object manifest manifestOptions.addHeader("x-object-manifest", containerName + "/" + partPrefix); // Upload the manifest—Swift will automatically combine the parts blobStore.putBlob(containerName, manifestBlob, manifestOptions);
Key Notes
- Static vs Dynamic Large Objects: Static requires all parts to be uploaded first, while Dynamic lets you add parts incrementally. Static is better for most use cases where you control the upload flow.
- Manifest Header: The
x-object-manifestheader follows the formatcontainer/part-prefix—Swift will match all objects starting with that prefix as parts of the large object. - Lower-Level Control: If you prefer using Swift’s native API directly, use the
SwiftApiandContainerApiinterfaces (as shown in Step 1) instead ofBlobStore—theputObjectmethod works withPutOptionsthe same way.
内容的提问来源于stack exchange,提问作者ibr

