Non-JSON Content Types
In addition to JSON-serializable data, tRPC can use FormData, File, and other Binary types as procedure inputs
Client Setup
While tRPC natively supports several non-json serializable types, your client may need a little link configuration to support them depending on your setup.
httpLink
supports non-json content types out the box, if you're only using this then your existing setup should work immediately
ts
import { httpLink } from '@trpc/client';trpc.createClient({links: [httpLink({url: 'http://localhost:2022',}),],});
ts
import { httpLink } from '@trpc/client';trpc.createClient({links: [httpLink({url: 'http://localhost:2022',}),],});
However, not all links support these new content types, if you're using httpBatchLink
or httpBatchStreamLink
you will need to include a splitLink and check which link to use depending on the content
ts
import {httpBatchLink,httpLink,isNonJsonSerializable,splitLink,} from '@trpc/client';trpc.createClient({links: [splitLink({condition: (op) => isNonJsonSerializable(op.input),true: httpLink({url,}),false: httpBatchLink({url,}),}),],});
ts
import {httpBatchLink,httpLink,isNonJsonSerializable,splitLink,} from '@trpc/client';trpc.createClient({links: [splitLink({condition: (op) => isNonJsonSerializable(op.input),true: httpLink({url,}),false: httpBatchLink({url,}),}),],});
FormData
Input
FormData is natively supported, and for more advanced usage you could also combine this with a library like zod-form-data to validate inputs in a type-safe way.
ts
import {z } from 'zod';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({hello :publicProcedure .input (z .instanceof (FormData )).query ((opts ) => {constdata =opts .input ;return {greeting : `Hello ${data .get ('name')}`,};}),});
ts
import {z } from 'zod';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({hello :publicProcedure .input (z .instanceof (FormData )).query ((opts ) => {constdata =opts .input ;return {greeting : `Hello ${data .get ('name')}`,};}),});
For a more advanced code sample you can see our example project here
File
and other Binary Type Inputs
tRPC converts many octet content types to a ReadableStream
which can be consumed in a procedure. Currently these are Blob
Uint8Array
and File
.
ts
import {octetInputParser } from '@trpc/server/http';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({upload :publicProcedure .input (octetInputParser ).query ((opts ) => {constdata =opts .input ;return {valid : true,};}),});
ts
import {octetInputParser } from '@trpc/server/http';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({upload :publicProcedure .input (octetInputParser ).query ((opts ) => {constdata =opts .input ;return {valid : true,};}),});