-
I'm trying to figure the best approach for handling images using orpc and r2 (although same would apply for s3) alongside openAPI and just had a few questions on the best way to handle things. How can we pass multiple mime types?As per the docs, we can only pass a single string as the type, but I would like to be able to specify an array of allowed types (not everything under Previously in Zod I would handle files using something like: const ImageFileSchema = z
.instanceof(File)
.refine((file) => file !== undefined, 'Image is required.')
.refine((file) => file.size <= 8388608, `Maximum file size is 8MB.`)
.refine(
(file) => ['image/jpeg', 'image/png'].includes(file.type),
'Only .jpeg and .png files are accepted.'
); And currently to get it mostly working I'm doing this: const ImageFileSchema = oz
.file()
.type("image/*") // <-- only allows one
.refine((file) => file.size <= 8388608, `Maximum file size is 8MB.`)
.refine(
(file) => ['image/jpeg', 'image/png'].includes(file.type),
'Only .jpg and .png files are accepted.'
)
.describe("The image file") Can we use detailed response?Normally in a fetch environment, we can just return a Response object that can be constructed from the r2 object (See the GET response). I'm trying to do a similar thing using oRPC and a const imagesContract = oc.router({
static: oc
.route({ method: "GET", path: "/images/static/{key}", description: "Download an image", outputStructure: "detailed" })
.errors({
NOT_FOUND: {}
})
.input(z.object({ key: z.string() }))
})
const imagesRouter = os.router({
static: os.static.handler(async ({ input, context }) => {
const r2File = await context._env.IMAGES.get(input.key)
if (!r2File) throw errors.NOT_FOUND()
const headers = new Headers();
r2File.writeHttpMetadata(headers);
headers.set("etag", r2File.httpEtag);
return {
body: r2File.body,
headers,
}
})
}) if I try and do the same thing with const imagesContract = oc.router({
static: oc
.route({ method: "GET", path: "/images/static/{key}", description: "Download an image", outputStructure: "compact" })
.errors({
NOT_FOUND: {}
})
.input(z.object({ key: z.string() }))
.output(ImageFileSchema)
})
const imagesRouter = os.router({
static: os.static.handler(async ({ input, context }) => {
const r2File = await context._env.IMAGES.get(input.key)
if (!r2File) throw errors.NOT_FOUND()
const blob = await r2File.blob()
const file = new File([blob], input.key, { type: r2File.httpMetadata?.contentType })
return file
})
}) Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
You need to convert the data into a For further optimization, you might also consider using lazy-file and |
Beta Was this translation helpful? Give feedback.
You need to convert the data into a
Blob
orFile
instance (in both compact/detailed mode), and the headers must be an object, as described hereFor further optimization, you might also consider using lazy-file and
r2File.body