ZephyrrrZ
Convex Community8mo ago
26 replies
Zephyrrr

How to Get File Size in onUpload with Convex R2 When getMetadata Returns Null?

Hi everyone,

I'm working with Convex and the R2 component for file uploads. My goal is to get the size of the uploaded file immediately after the upload completes, specifically within the onUpload callback, so I can track storage usage per user.

The issue I'm encountering is that when I call r2.getMetadata(ctx, key) inside the onUpload function, it returns null. I suspect this is because onUpload might be running as part of the syncMetadata process, and the metadata isn't fully available or settled at that exact moment through r2.getMetadata.

Here's the relevant part of my r2.clientApi configuration:
export const { generateUploadUrl, syncMetadata } = r2.clientApi({
  checkUpload: async (ctx, bucket) => {
    const user = await ctx.runQuery(api.users.current);
    if (!user) {
      throw new ConvexError("unauthorized");
    }
    // TODO: check if the storage is full
  },
  onUpload: async (ctx, key) => {
    // Problem: metadata is null here
    const metadata = await r2.getMetadata(ctx, key);
    console.log("Metadata in onUpload:", metadata);

    const user = await ctx.runQuery(api.users.current);
    if (!user || !metadata) {
      return;
    }

    await totalStorageAggregate.insert(ctx, {
      key: user._id,
      id: key,
      sumValue: metadata.size, // metadata.size would be undefined if metadata is null
    });
  },
  onDelete: async (ctx, key) => {
    const user = await ctx.runQuery(api.users.current);
    if (!user) {
      throw new ConvexError("unauthorized");
    }

    await totalStorageAggregate.delete(ctx, {
      key: user._id,
      id: key,
    });
  },
});

How can I reliably get the file size (and other metadata) for a newly uploaded file within the Convex backend flow, ideally associated with the onUpload event or shortly thereafter?

Any insights, examples, or alternative approaches would be greatly appreciated!

Thanks!
Was this page helpful?