Skip to content

Binary Data

File, Blob, and ReadableStream<Uint8Array> are supported by the RPC Serializer and OpenAPI Serializer. Use them to handle binary data in your procedures.

WARNING

To better support Blob, File, and ReadableStream<Uint8Array> at the root level in cross-origin scenarios, extend your CORS allowlist to allow clients to send and receive the Content-Disposition and Standard-Server headers. Learn more in the Standard Server documentation. If you use the CORS Plugin, include them in allowHeaders and exposeHeaders:

ts
const cors = new CORSHandlerPlugin({
  allowHeaders: ['Content-Disposition', 'Standard-Server'],
  exposeHeaders: ['Content-Disposition', 'Standard-Server'],
})

File and Blob

Procedures can accept File and Blob as input and return them directly or inside nested structures.

WARNING

File and Blob are usually buffered in memory by default. For large files, we recommend extending the body parser for better performance and reliability.

ts
const 
example
=
os
.
input
(
z
.
file
())
.
output
(
z
.
object
({
anyFieldName
:
z
.
instanceof
(
File
) }))
.
handler
(async ({
input
}) => {
const
file
=
input
console
.
log
(
file
.
name
)
return {
anyFieldName
: new
File
(['Hello World'], 'hello.txt', {
type
: 'text/plain' }),
} })

ReadableStream<Uint8Array>

Procedures can return ReadableStream<Uint8Array> to stream binary responses. The example below uses the Response Headers Plugin to set the appropriate Content-Type header.

ts
const 
example
=
base
.
output
(
z
.
instanceof
(
ReadableStream
))
.
handler
(async ({
context
}) => {
context
.
resHeaders
?.
set
('Content-Type', 'text/plain')
const
stream
= new
ReadableStream
<
Uint8Array
>({
start
(
controller
) {
controller
.
enqueue
(new
TextEncoder
().
encode
('Hello World'))
controller
.
close
()
} }) return
stream
})

Released under the MIT License.