Created
April 5, 2024 15:22
-
-
Save alexanderson1993/77d7ca83314fbf5965944055babef4fe to your computer and use it in GitHub Desktop.
A Remix upload handler for R2 buckets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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