The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Generate the PDF first, then upload the resulting file, byte array, or input stream with the AWS SDK for Java 2.x. Use RequestBody.fromFile for a file, RequestBody.fromBytes for an in-memory document, and RequestBody.fromInputStream when you have a stream and its exact length. The S3 upload does not create the PDF; it sends bytes your Java application has already produced.
Choose the upload shape that matches your PDF generator
PDF libraries expose output differently. Select the S3 request body that matches that output rather than converting everything unnecessarily.
| PDF output | SDK 2.x body | Best fit | Main caveat |
|---|---|---|---|
Local Path or file |
RequestBody.fromFile(path) |
The generator already writes to disk; large documents | Requires temporary-file storage and cleanup |
byte[] |
RequestBody.fromBytes(bytes) |
Small or moderate PDFs already held in memory | Memory use is approximately the PDF size, plus application overhead |
InputStream with known size |
RequestBody.fromInputStream(stream, exactLength) |
Streaming generation or an existing stream | An incorrect length can truncate, stall, or fail the request |
| Unknown-length stream | An SDK-supported buffering provider or multipart design | Large streams whose size cannot be known in advance | Synchronous buffering can consume the complete stream in memory |
SDK 2.x uses RequestBody for synchronous calls and AsyncRequestBody for asynchronous calls. Do not paste SDK 1.x upload signatures into a 2.x project.
Prerequisites and object naming
- An AWS account, an S3 bucket, and credentials available through the standard AWS credential provider chain (for example, an IAM role, environment variables, or a local profile).
- A Java project containing the AWS SDK for Java 2.x S3 module. Keep the SDK version aligned with the rest of your dependency management rather than copying an unpinned version into production.
- An S3 region that matches the bucket, or a client configuration that can resolve the bucket’s region.
- A unique object key such as
invoices/2026/09/invoice-1042.pdf. A key is not a local path; it is the name under which S3 stores the object.
Grant only the permissions required by the application, normally s3:PutObject for the target prefix. Add encryption, tagging, or ACL headers only when your bucket policy requires them.
Recommended Free Tools
Upload a generated PDF file synchronously
This is the simplest path when your PDF library writes to a temporary or permanent file. The following SDK 2.x fragment assumes pdfPath already points to a completed PDF.
import java.nio.file.Path;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
public final class PdfUploader {
public static void uploadFile(S3Client s3, Path pdfPath,
String bucket, String key) {
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType("application/pdf")
.build();
s3.putObject(request, RequestBody.fromFile(pdfPath));
}
}
Call uploadFile only after the PDF writer has closed its output. Closing the writer first ensures all cross-reference and trailer bytes have reached the file. The method returns after the synchronous operation completes or throws an exception.
Upload a PDF held in a byte array
When the generator returns byte[], avoid writing a needless intermediate file:
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
public static void uploadBytes(S3Client s3, byte[] pdf,
String bucket, String key) {
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType("application/pdf")
.build();
s3.putObject(request, RequestBody.fromBytes(pdf));
}
This approach is straightforward for documents that comfortably fit your heap. For a service handling concurrent reports, account for every simultaneous byte array before choosing this method.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #2
Upload an InputStream with an exact content length
For a stream, the length argument is a correctness requirement, not an estimate. AWS guidance is explicit: “Always provide the exact content length when it’s available.” A value smaller than the actual byte count can truncate the object; a value larger than the bytes available can make the request fail or wait for data that never arrives.
import java.io.InputStream;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
public static void uploadStream(S3Client s3, InputStream pdfInputStream,
long pdfLength, String bucket, String key) {
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType("application/pdf")
.build();
s3.putObject(request,
RequestBody.fromInputStream(pdfInputStream, pdfLength));
}
Do not reuse or close the stream before putObject has returned. Use try-with-resources when your method owns the stream, and close it on both success and failure.
When the stream length is unknown
An unknown-length synchronous provider may buffer the complete stream to determine its length. That can be unsuitable for large PDFs or many concurrent uploads. For large unknown-length data, consider an S3 multipart-upload design or an asynchronous approach documented by the SDK that supports unknown lengths. Choose based on document size, available memory, and whether your request thread can remain occupied.
Asynchronous upload and transfer completion
An asynchronous method returning a future does not mean the object is already durable. Keep and observe the completion stage, and close the client only after the transfer has completed (or after your application has deliberately handed lifecycle ownership elsewhere).
Async client with a file
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public static CompletableFuture<PutObjectResponse> uploadFileAsync(
S3AsyncClient s3, Path pdfPath, String bucket, String key) {
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucket)
.key(key)
.contentType("application/pdf")
.build();
return s3.putObject(request, AsyncRequestBody.fromFile(pdfPath));
}
Use future.join() or, preferably, attach thenAccept and exceptionally handlers according to your application’s execution model. AWS also documents S3 Transfer Manager for file uploads; it exposes a completion future that you should await when subsequent work depends on the object being uploaded.
Metadata, integrity, and lifecycle checks
- Set
contentType("application/pdf")so consumers receive the intended media type. - Use deterministic keys only when replacement is intentional. Otherwise include an invoice ID, version, or generated identifier.
- Never report success merely because PDF generation succeeded. Treat generation and upload as separate states in logs and job records.
- For retries, use an idempotent key or a run identifier so a retry cannot silently overwrite an unrelated document.
- Delete temporary files after the upload future completes, not when the request is merely submitted.
Common failures and fixes
AccessDenied
The caller lacks permission for the bucket or key prefix, or a bucket policy denies the request. Check the active credential identity, region, key ARN, and required encryption headers.
NoSuchBucket or wrong region
Verify the bucket name exactly and configure the S3 client for the bucket’s region. A region mismatch can also appear as a redirect or signature error.
Truncated or hanging stream upload
Recalculate the exact byte length from the source. Never use character count for encoded PDF data, and never guess a stream length. If the size cannot be known without buffering, use a design intended for unknown length or multipart upload.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #4
OutOfMemoryError
A byte-array upload or unknown-length buffering path may hold the complete PDF in memory. Switch to a file-backed upload, bound concurrency, or use multipart transfer.
PDF opens locally but not from S3
Confirm the writer was closed before upload, the object size matches the generated bytes, and the object has application/pdf metadata. A successful HTTP response does not repair an incomplete PDF.
Async application exits early
Keep the completion future, await it, or keep the service alive until the future reports success. Close the asynchronous client after outstanding work is complete.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Performance and cost decisions
There is no universal fastest method in the available AWS guidance. A local file avoids retaining the entire PDF as a Java array but adds disk I/O. Bytes minimize moving parts for small documents but increase heap pressure. Streams avoid a separate file, yet exact length and buffering behavior become your responsibility. Multipart or asynchronous transfers are architectural choices for large data, not automatic guarantees of a particular throughput.
Best Value
S3 charges depend on your AWS account’s region, storage class, request volume, and transferred data. This Java code does not change those service charges. Measure your own workload and account for retries and concurrent jobs when setting timeouts and memory limits.
Or skip the browser setup
If the PDF begins as a webpage capture rather than a server-side PDF document, ScreenshotNeo can return a PDF from one request, after which your Java code can upload the response bytes to S3. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.
See the ScreenshotNeo API documentation for request options. A Java application can call the PDF endpoint like this (adapt the URL and parameters to your capture):
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.screenshotneo.com/v1/shot?access_key=YOUR_API_KEY&url=https%3A%2F%2Fstripe.com&format=pdf"))
.GET().build();
byte[] pdf = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofByteArray()).body();
Files.write(Path.of("shot.pdf"), pdf);
For a direct command-line call, use curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Should I upload the PDF before closing the generator?
No. Finish and close the PDF writer first so all document structures have been written before the S3 request reads the bytes.
Can I use an SDK 1.x example in an SDK 2.x project?
Not unchanged. SDK 2.x uses RequestBody and AsyncRequestBody; adapt the example to the APIs and modules in your dependency set.
Is a successful putObject call enough for an asynchronous upload?
Only after the returned completion stage reports success. Submission of an asynchronous request is not completion.
The Bottom Line
Generate and finalize the PDF, choose file, bytes, or an exactly sized stream, then wait for synchronous or asynchronous completion before declaring the S3 object ready.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesQuick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

