java
AWS SDK for Java v2
Install
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.29.0</version>
</dependency>Configure
Configure the endpoint, region, credential and bucket in this tool’s vocabulary. Path-style addressing is recommended for dotted bucket names and clients without nested wildcard TLS, but virtual-hosted addressing is also supported.
| In AWS SDK for Java v2 | Set it to |
|---|---|
| endpointOverride | https://s3.canada.popcloud.ca |
| region | canada |
| AwsBasicCredentials.create | PCAK00EXAMPLEKEYID00 |
| AwsBasicCredentials.create | <your secret access key> |
| forcePathStyle | true |
export AWS_ACCESS_KEY_ID=PCAK00EXAMPLEKEYID00
export AWS_SECRET_ACCESS_KEY=<your secret access key>
export AWS_ENDPOINT_URL=https://s3.canada.popcloud.ca
export AWS_REGION=canada
export POPCLOUD_BUCKET=pc-your-org-mediaThese are example values. Sign in and every snippet on this site fills in with your own endpoint, key and bucket.
static S3Client newClient() {
return S3Client.builder()
.endpointOverride(URI.create(System.getenv("AWS_ENDPOINT_URL"))) // https://s3.<region>.popcloud.ca
.region(Region.of(System.getenv("AWS_REGION"))) // canada
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(
System.getenv("AWS_ACCESS_KEY_ID"),
System.getenv("AWS_SECRET_ACCESS_KEY"))))
// Recommended for predictable custom-endpoint behavior. Virtual-hosted
// requests are supported too for ordinary single-label bucket names.
.forcePathStyle(true)
.build();
}Use it
Upload an object
static void upload(S3Client s3, String bucket, String key, byte[] body) {
s3.putObject(
PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType("text/plain")
.build(),
RequestBody.fromBytes(body));
}Download an object
static byte[] download(S3Client s3, String bucket, String key) {
return s3.getObjectAsBytes(
GetObjectRequest.builder().bucket(bucket).key(key).build())
.asByteArray();
}List a prefix
static List<String> listPrefix(S3Client s3, String bucket, String prefix) {
List<String> keys = new ArrayList<>();
s3.listObjectsV2Paginator(
ListObjectsV2Request.builder().bucket(bucket).prefix(prefix).build())
.contents()
.forEach((S3Object object) -> keys.add(object.key()));
return keys;
}Presign a URL
static URL presign(String bucket, String key) {
try (S3Presigner presigner = S3Presigner.builder()
.endpointOverride(URI.create(System.getenv("AWS_ENDPOINT_URL")))
.region(Region.of(System.getenv("AWS_REGION")))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(
System.getenv("AWS_ACCESS_KEY_ID"),
System.getenv("AWS_SECRET_ACCESS_KEY"))))
// The presigner needs path style told to it separately from the client.
.serviceConfiguration(software.amazon.awssdk.services.s3.S3Configuration.builder()
.pathStyleAccessEnabled(true)
.build())
.build()) {
return presigner.presignGetObject(GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofHours(1)) // 7 days is the maximum
.getObjectRequest(GetObjectRequest.builder()
.bucket(bucket)
.key(key)
.build())
.build())
.url();
}
}Delete an object
static void delete(S3Client s3, String bucket, String key) {
s3.deleteObject(DeleteObjectRequest.builder().bucket(bucket).key(key).build());
}What to watch for
These apply to AWS SDK for Java v2 specifically. The full list covers the platform.
- You’ll see
- 501 NotImplemented on an upload whose x-amz-content-sha256 is STREAMING-AWS4-HMAC-SHA256-PAYLOAD.
- Why
- That encoding signs every chunk of the body separately, which a re-signing proxy cannot forward without buffering the whole object. The platform streams instead, and never holds a body in memory.
- Instead
- Nothing to do on a current SDK — the modern default is STREAMING-UNSIGNED-PAYLOAD-TRAILER, which works, checksum trailer and all. Only older SDK versions and explicitly-configured chunked signing hit this. If you do, set the payload signing option off (`AWS_S3_DISABLE_CHUNKED_ENCODING`, `chunkedEncodingEnabled=false`, or the equivalent) and the SDK falls back to a supported encoding.
- You’ll see
- 405 MethodNotAllowed from CreateBucket or DeleteBucket — `aws s3 mb`, `mc mb`, or a tool provisioning its own bucket on first run.
- Why
- Bucket lifecycle belongs to the control plane, which also allocates the storage account, the data-plane key and the CORS rules that come with it. Letting the edge create buckets would create half of one.
- Instead
- Create buckets in the dashboard, or with `POST /v1/buckets` on the control-plane API. Everything object-level then works normally against that bucket.
How this page is kept true
Every snippet above was extracted from examples/java/aws-sdk-java-v2, a program that uploads, downloads, compares bytes, lists, presigns and cleans up after itself. It runs in CI against a live sandbox organisation via make docs-verify-java. If it stops passing, this page is wrong and we treat that as a bug in the product.
Not yet run against the live sandbox — the runner is wired, the first verified run stamps this line.