Skip to content

Instantly share code, notes, and snippets.

@alexanderson1993
Created April 5, 2024 15:22
Show Gist options
  • Save alexanderson1993/77d7ca83314fbf5965944055babef4fe to your computer and use it in GitHub Desktop.
Save alexanderson1993/77d7ca83314fbf5965944055babef4fe to your computer and use it in GitHub Desktop.
A Remix upload handler for R2 buckets
import type { UploadHandlerPart } from "@remix-run/cloudflare";
export class MaxPartSizeExceededError extends Error {
constructor(public field: string, public maxBytes: number) {
super(`Field "${field}" exceeded upload size of ${maxBytes} bytes.`);
}
}
export function createR2UploadHandler({
bucket,
key,
maxPartSize = 3000000,
filter,
}: {
bucket: R2Bucket;
key: (args: Omit<UploadHandlerPart, "data">) => string;
maxPartSize?: number;
filter?: (
args: Omit<UploadHandlerPart, "data">
) => boolean | Promise<boolean>;
}) {
return async ({ name, contentType, data, filename }: UploadHandlerPart) => {
if (
filter &&
!(await filter({
filename,
contentType,
name,
}))
) {
return undefined;
}
let size = 0;
const chunks = [];
for await (const chunk of data) {
size += chunk.byteLength;
if (size > maxPartSize) {
throw new MaxPartSizeExceededError(name, maxPartSize);
}
chunks.push(chunk);
}
const object = await bucket.put(
key({ name, contentType, filename }),
new Blob(chunks, {
type: contentType,
})
);
return object?.key;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment