I've got a sample program here that shows uploading a payload via an 
InputStream (ByteBufferBackedInputStream below - I've also tried it with a 
FileInputStream). I can't use a ByteSource because it doesn't support sourcing 
from direct access memory buffers.

```
public class App 
{
    public static void main( String[] args ) throws Exception
    {
        Properties overrides = new Properties();
        overrides.setProperty(PROPERTY_S3_VIRTUAL_HOST_BUCKETS, "false");
        overrides.setProperty(PROPERTY_STRIP_EXPECT_HEADER, "true");

        String endpoint = "http://localhost:9444/s3";;
        if (endpoint != null) {
            URI uri = URI.create(endpoint);
            String path = uri.getPath();
            if (path != null && !path.isEmpty()) {
                overrides.setProperty(PROPERTY_S3_SERVICE_PATH, path);          
// <-- "/s3" required
            }
        }
        BlobStoreContext context = ContextBuilder.newBuilder("aws-s3")
                .endpoint(endpoint)                                             
// <-- "/s3" required
                .credentials("key", "secret")
                .overrides(overrides)
                .buildView(BlobStoreContext.class);

        BlobStore blobStore = context.getBlobStore();

        ByteBuffer content = ByteBuffer.allocate(1024 * 1024);
        new Random(Instant.now().getEpochSecond()).nextBytes(content.array());

        ByteBuffer tmp = content.duplicate();
        HashCode md5 = Hashing.md5().hashBytes(tmp);

        try (ByteBufferBackedInputStream is = new 
ByteBufferBackedInputStream(content)) {
            Blob blob = blobStore.blobBuilder("myblob")
                        .payload(is)
//                        .payload(content.array())
                        .contentLength(content.remaining())
                        .contentMD5(md5)
                        .build();
            blobStore.putBlob("ninja-autod71326c6-b718-46d2-bbd9-5c259ddd3bba", 
blob);
        }
        context.close();
    }

    private static class ByteBufferBackedInputStream extends InputStream {

        private final ByteBuffer buf;

        public ByteBufferBackedInputStream(ByteBuffer buf) {
            this.buf = buf;
        }

        @Override
        public int read() {
            if (!buf.hasRemaining()) {
                return -1;
            }
            return buf.get() & 0xFF;
        }

        @Override
        public int read(@Nonnull byte[] bytes, int off, int len) {
            if (!buf.hasRemaining()) {
                return -1;
            }
            int lenToUse = Math.min(len, buf.remaining());
            buf.get(bytes, off, lenToUse);
            return lenToUse;
        }
    }
}
```

The error returned by an s3 ninja server is 400 bad request, with the reason 
being the md5 checksums do not match (the one I calculated with Hashing.md5() 
and the one the server calculated). 

I've tried the same request with the same content using payload(byte[]) and it 
works. Uncomment the other payload line and comment out the payload(is) line 
and re-execute. It works.

```
Exception in thread "main" org.jclouds.http.HttpResponseException: command: PUT 
http://172.29.83.131:9444/s3/ninja-autod71326c6-b718-46d2-bbd9-5c259ddd3bba/byHashV1/0001000000000040000020DB64B417264C5CE81AC0F85D855F6088D717463C5C7CC7574AA19CAD7B45C1BC
 HTTP/1.1 failed with response: HTTP/1.1 400 Bad Request; content: [
<html>
<head>
<title>Error - 400</title>
</head>
<body>
<h1>Bad Request</h1>
<hr />
<pre>Invalid MD5 checksum (Input: PaLqlfshFBMNUqyw+NT54A==, Expected: 
4HWv1+2bHosUPzq8OUeMmQ==)</pre>
<hr />
<p>
..
</body>
</html>]
        at 
org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent.handleError(ParseAWSErrorFromXmlContent.java:82)
        at 
org.jclouds.http.handlers.DelegatingErrorHandler.handleError(DelegatingErrorHandler.java:65)
        at 
org.jclouds.http.internal.BaseHttpCommandExecutorService.shouldContinue(BaseHttpCommandExecutorService.java:138)
        at 
org.jclouds.http.internal.BaseHttpCommandExecutorService.invoke(BaseHttpCommandExecutorService.java:107)
        at 
org.jclouds.rest.internal.InvokeHttpMethod.invoke(InvokeHttpMethod.java:91)
        at 
org.jclouds.rest.internal.InvokeHttpMethod.apply(InvokeHttpMethod.java:74)
        at 
org.jclouds.rest.internal.InvokeHttpMethod.apply(InvokeHttpMethod.java:45)
        at 
org.jclouds.rest.internal.DelegatesToInvocationFunction.handle(DelegatesToInvocationFunction.java:156)
        at 
org.jclouds.rest.internal.DelegatesToInvocationFunction.invoke(DelegatesToInvocationFunction.java:123)
        at com.sun.proxy.$Proxy48.putObject(Unknown Source)
        at org.jclouds.s3.blobstore.S3BlobStore.putBlob(S3BlobStore.java:271)
        at 
org.jclouds.aws.s3.blobstore.AWSS3BlobStore.putBlob(AWSS3BlobStore.java:85)
        at org.jclouds.s3.blobstore.S3BlobStore.putBlob(S3BlobStore.java:248)
        at test.App.main(App.java:98)

Process finished with exit code 1
```

Thanks in advance,
John Calcote

Reply via email to