videosphere
    Preparing search index...

    Function getPresignedUploadUrl

    • Generate presigned upload URL for direct browser uploads

      Parameters

      • key: string

        Object key in R2 bucket (e.g., "users/123/videos/abc.mp4")

      • contentType: string

        MIME type of file being uploaded (e.g., "video/mp4")

      • contentLength: number

        Exact file size in bytes (validated server-side after upload via HEAD)

      Returns Promise<string>

      Presigned PUT URL that expires in 15 minutes

      Security:

      • Content-Type is locked into the signature, preventing upload of wrong file types.
      • Content-Length is NOT signed here because browsers treat it as a "forbidden" request header and set it automatically from the body. Signing it would cause R2 to reject every browser upload with a SignatureDoesNotMatch error. Size enforcement is handled server-side in POST /api/uploads/[jobId]/complete via a HEAD request that checks the object's actual byte count against the declared fileSize (layer 2).
      const url = await getPresignedUploadUrl("users/123/video.mp4", "video/mp4", 1024 * 1024);
      // Client can PUT file directly to R2 with this URL
      fetch(url, { method: "PUT", body: file, headers: { "content-type": "video/mp4" } })