Presigned URLs for Fast and Safe R2 Downloads
Last updated:
MV3 service workers can trigger downloads via chrome.downloads.download
. For Cloudflare R2, the most robust approach is to generate
a presigned GET URL and hand it to the browser. This avoids complex header signing and filename encoding pitfalls.
Generate a presigned URL
// utils/s3-fixed.js (excerpt)
export async function s3PresignGetObjectUrl({ accountId, bucket, key, accessKeyId, secretAccessKey, expires = 300 }) {
// Build canonical query with X-Amz-* params and computed signature
// Return URL like: https://{account}.r2.cloudflarestorage.com/{bucket}/{key}?X-Amz-Algorithm=...&X-Amz-Signature=...
}
Start the download
// background.js (excerpt)
const url = await s3PresignGetObjectUrl({ accountId, bucket, key, accessKeyId, secretAccessKey, expires: 300 });
await chrome.downloads.download({ url, filename: key.split('/').pop(), saveAs: false });
Why presigned?
- Minimizes request headers, avoiding signature mismatches.
- Leverages the browser’s downloader for reliability and UX.
- Scopes access tightly with an expiration window.
See also: AWS SigV4 in the Browser for R2.