#pre-signed url convex storage
1 messages · Page 1 of 1 (latest)
Hi @prime reef. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Currently, Convex's built-in ctx.storage.getUrl() does not produce expiring/signed URLs — the generated URL does not expire. [file storage discussion]
Options for short-lived / signed URLs
1. Use the Cloudflare R2 Component (recommended)
The @convex-dev/r2 component stores files in Cloudflare R2 instead of Convex native storage, and generates signed, expiring URLs via the S3-compatible API. You can control the expiration time:
// convex/listMessages.ts
import { components } from "./_generated/api";
import { query } from "./_generated/server";
import { R2 } from "@convex-dev/r2";
const r2 = new R2(components.r2);
export const list = query({
args: {},
handler: async (ctx) => {
const messages = await ctx.db.query("messages").collect();
return Promise.all(
messages.map(async (message) => ({
...message,
imageUrl: await r2.getUrl(
message.imageKey,
{
expiresIn: 60 * 60 * 24, // 1 day (default is 900s / 15 minutes)
},
),
})),
);
},
});
Notably, getSignedUrl from @aws-sdk/s3-request-presigner works in the Convex runtime (without making external requests), so it can be used inside a query — not just actions. [S3 signed URLs discussion]
2. Use the Convex Files Control Component
The @gilhrpenner/convex-files-control component supports download grants with max uses, expiration, and optional passwords, and works with both Convex storage and Cloudflare R2. [Convex Files Control]
3. Serve files via HTTP actions (access control at serve time)
If you want to keep using Convex native storage but add auth checks, you can serve files through an HTTP action that validates the request before returning the file. However, note that HTTP action responses are limited to 20MB. [serving files]
Summary: Native Convex storage URLs do not expire. If you need short-lived signed URLs, the Cloudflare R2 component is the most direct equivalent to S3/R2 pre-signed URLs.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@prime reef Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@twin ferry what are the limits of the Convex Files Control Component? i would assume the same as the http actions limited to 20MB?
Let me check the knowledge base for you again. One moment! :books:
The knowledge sources don't explicitly document specific limits for the Convex Files Control component itself. However, based on what's available:
- HTTP upload/download route: Since it uses HTTP actions under the hood, the 20MB request/response size limit applies. [HTTP Actions limits]
- Presigned URL upload flow: This bypasses the HTTP action size limit by uploading directly to Convex storage (or R2). The presigned URL flow has no specific file size limit — Convex's native upload URL approach states "the file size is not limited, but the upload POST request has a 2 minute timeout." [upload via URLs]
- Function argument size: 16 MiB for standard functions (5 MiB for Node.js actions). [function limits]
So your assumption is correct for the HTTP route method — it's capped at 20MB. But if you use the presigned URL flow (which the component also supports), you can upload arbitrarily large files. The component's useUploadFile hook supports both methods:
// HTTP route (limited to 20MB)
await uploadFile({ file, method: "http", provider: "convex" });
// Presigned (no file size limit)
await uploadFile({ file, method: "presigned", provider: "convex" });