JCLOUDS-964: S3 multipart copy

This commit is contained in:
Andrew Gaul 2015-10-14 21:38:32 -07:00
parent 0c1de23a9a
commit 4829bbbd2c
3 changed files with 56 additions and 0 deletions

View File

@ -678,6 +678,18 @@ public interface S3Client extends Closeable {
@PathParam("key") String key, @QueryParam("partNumber") int partNumber,
@QueryParam("uploadId") String uploadId, Payload part);
@Named("UploadPartCopy")
@PUT
@Path("/{key}")
@Headers(keys = {"x-amz-copy-source", "x-amz-copy-source-range"}, values = {"/{sourceBucket}/{sourceObject}", "bytes={startOffset}-{endOffset}"})
@ResponseParser(ETagFromHttpResponseViaRegex.class)
String uploadPartCopy(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class) @BinderParam(
BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
@PathParam("key") String key, @QueryParam("partNumber") int partNumber,
@QueryParam("uploadId") String uploadId,
@PathParam("sourceBucket") String sourceBucket, @PathParam("sourceObject") String sourceObject,
@PathParam("startOffset") long startOffset, @PathParam("endOffset") long endOffset);
/**
*
This operation completes a multipart upload by assembling previously uploaded parts.

View File

@ -551,6 +551,31 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
}
}
public void testMultipartCopy() throws Exception {
String containerName = getContainerName();
try {
String fromObject = "fromObject";
S3Object object = getApi().newS3Object();
object.getMetadata().setKey(fromObject);
object.setPayload(oneHundredOneConstitutions);
object.getMetadata().getContentMetadata().setContentLength(oneHundredOneConstitutions.size());
getApi().putObject(containerName, object);
String toObject = "toObject";
String uploadId = getApi().initiateMultipartUpload(containerName, ObjectMetadataBuilder.create().key(toObject).build());
String eTagOf1 = getApi().uploadPartCopy(containerName, toObject, 1, uploadId, containerName, fromObject, 1, oneHundredOneConstitutions.size() - 1);
String eTag = getApi().completeMultipartUpload(containerName, toObject, uploadId, ImmutableMap.of(1, eTagOf1));
assertThat(eTag).isNotEqualTo(eTagOf1);
object = getApi().getObject(containerName, toObject);
assertEquals(ByteStreams2.toByteArrayAndClose(object.getPayload().openStream()), oneHundredOneConstitutions.slice(1, oneHundredOneConstitutions.size() - 1).read());
} finally {
returnContainer(containerName);
}
}
public void testDeleteMultipleObjects() throws InterruptedException {
String container = getContainerName();
try {

View File

@ -550,6 +550,25 @@ public abstract class S3ClientTest<T extends S3Client> extends BaseS3ClientTest<
checkFilters(request);
}
public void testUploadPartCopy() throws SecurityException, NegativeArraySizeException, NoSuchMethodException {
Invokable<?, ?> method = method(S3Client.class, "uploadPartCopy", String.class, String.class, int.class,
String.class, String.class, String.class, long.class, long.class);
GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("bucket", "foo", 1, "asdsadasdas",
"anotherBucket", "anotherObject", 2, 10 * 1024 * 1024));
assertRequestLineEquals(request, "PUT https://bucket." + url + "/foo?partNumber=1&uploadId=asdsadasdas HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: bucket." + url + "\n" +
"x-amz-copy-source: /anotherBucket/anotherObject\n" +
"x-amz-copy-source-range: bytes=2-10485760\n");
assertPayloadEquals(request, null, "application/unknown", false);
assertResponseParserClassEquals(method, request, ETagFromHttpResponseViaRegex.class);
assertSaxResponseParserClassEquals(method, null);
assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(request);
}
public void testCompleteMultipartUpload() throws SecurityException, NegativeArraySizeException,
NoSuchMethodException {
Invokable<?, ?> method = method(S3Client.class, "completeMultipartUpload", String.class, String.class,