get-convex / get-convex/r2

Add support for content-disposition to r2.getUrl

Open
#34 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
49
Forks
26
Avg merge
6h 22m
Merged PRs (30d)
1

Description

### Summary

Please add built-in support in `@convex-dev/r2` for generating signed URLs that force file download with a specific filename (i.e. `Content-Disposition: attachment; filename=...`).

### Problem

Right now, `r2.getUrl(key, { expiresIn })` is great for basic access, but it does not let me control download behavior/filename.

In static frontend apps, this causes browser-dependent behavior:
- PDFs/images often open inline instead of downloading
- `_blank`-based workarounds can trigger popup blockers (notably Safari)
- `` is unreliable for cross-origin signed URLs

To get reliable downloads with a chosen filename, I currently have to bypass the component and manually use AWS SDK presigning with `ResponseContentDisposition`. That adds extra dependencies and duplicated signing logic in app code.

### Proposed API

Any of these would solve allowing downloads with a particular filename:

1. Extend `getUrl` options:
```ts
await r2.getUrl(key, {
expiresIn: 900,
disposition: "attachment",
filename: "Pitch Deck.pdf",
});
```
2. Or add a convenience method:
```ts
await r2.getDownloadUrl(key, {
expiresIn: 900,
filename: "Pitch Deck.pdf",
});
```

Separately for full control, allow user to set the content-disposition:
```ts
r2.getUrl(key, {
expiresIn: 900,
contentDisposition: `attachment; ...`
}
```

### Expected behavior
- Returned URL forces download (attachment), not inline render.
- Download uses the provided filename.
- UTF-8 filename support should be handled correctly.
- Backward-compatible with existing getUrl usage.

Contributor guide

Open the contributing guide

Research direction

Locate the `getUrl` entry point and inspect how signed URL options are passed to Cloudflare R2. Compare the proposed option shapes and determine how content disposition and UTF-8 filenames should be encoded without changing existing usage. Done means generated URLs force attachment downloads with the requested filename while preserving current behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend, cloud
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.