writing a fast S3 preview utility in node.js.
While adapting to a new requirement on a recent work project, which was switching from a system that self-uploads images to AWS and returns HTTPS URLs to one that communicates with an existing service and responds with S3 URIs, i faced a familiar local-development dilemma.
I wanted to keep my existing logic, which was better for debugging, but it wasn’t useful for that production. My options were to default to the AWS command-line client or a GUI like Cyberduck, but switching between multiple apps would become a bottleneck to my pace.
The solution? A quick, disposable CLI tool.
Amazon S3 supports presigned URLS—temporary links that grant access to a private object for a limited time. If you already have permission to read the object, you can generate a URL that borrows that permission and expires automatically.
With Node.js and AWS SDK v3, this is straightforward. And since the goal isn’t to build a service, but a fast utility I can run locally, I only needed two dependencies:
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
Here’s the entire utility in a small, maintainable block:
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const s3Client = new S3Client({
region: process.env.REGION
});
async function generatePreview(s3Uri) {
try {
// Parse bucket and key from s3:// URL
const urlParts = s3Uri.replace("s3://", "").split("/");
const bucket = urlParts.shift();
const key = urlParts.join("/");
const command = new GetObjectCommand({
Bucket: bucket,
Key: key,
});
// Generate signed URL (expires in 1 hour)
const signedUrl = await getSignedUrl(s3Client, command, {
expiresIn: 3600
});
console.log("\n Browser Preview Link:");
console.log("--------------------------------------------");
console.log(signedUrl);
console.log("--------------------------------------------\n");
} catch (err) {
console.error("Error generating URL:", err);
}
}
// Read input from CLI
const inputPath = process.argv[2];
if (!inputPath) {
console.log("Usage: node preview.js s3://your-bucket/path/to/file");
} else {
generatePreview(inputPath);
}
Run it like this:
node preview.js s3://your-bucket/path/to/image.jpg
The output is a temporary URL you can open directly in your browser.
Why This Works
Presigned URLs don’t make objects public. They simply delegate your existing s3:GetObject permission for a short time. If you can’t read the object, the URL won’t work. If you can, the link is valid until it expires & no bucket policy changes required.