oRPC
background

File Upload

How to upload files with oRPC?

Introduction

oRPC simplifies file uploads, providing built-in support for handling files seamlessly without any restriction or configuration. This guide walks you through the process of uploading files using oRPC.

Basic File Upload Example

oRPC allows you to define file upload handlers with ease. In this example, we define an endpoint that accepts a file input:

import { os } from '@orpc/server'
import { z } from 'zod'
 
export const uploadFile = os.input(
    z.object({ file: z.instanceof(File) })
).func(async (input) => {
    const file: File = input.file
    // Handle the file as needed, e.g., save to storage, process, etc.
})

Note: The z.instanceof(File) schema used here works well for basic usage but may not provide full validation or flexibility for complex requirements.

Enhanced File Upload with @orpc/zod

To improve file type validation, oRPC offers additional schemas in the @orpc/zod package. This includes specialized schemas for common types like File, Blob, URL, and RegExp. With these, you can apply more granular constraints, such as file type filtering for images or other media formats.

Using the Enhanced File Schema

Here's an example using oz.file() from @orpc/zod, which allows specifying a file type restriction for images:

import { os } from '@orpc/server'
import { oz } from '@orpc/zod'
import { z } from 'zod'
 
export const uploadFile = os.input(
    z.object({ file: oz.file().type('image/*') })
).func(async (input) => {
    const image: File = input.file 
    // Process the image file as needed
})
 
export const appRouter = os.router({
  uploadFile,
})

In this example, oz.file().type('image/*') restricts uploads to image files only, improving type safety and preventing invalid file types from being uploaded.

Client Usage for File Upload

To upload files with oRPC from the client, set up an oRPC client and pass a File object directly to the upload endpoint.

import { createORPCClient } from '@orpc/client'
 
const client = createORPCClient<typeof appRouter>({
  baseURL: 'http://localhost:3000',
})
 
// Example: Upload a file from an HTML file input
const fileInput = document.getElementById('file-input') as HTMLInputElement
fileInput.onchange = async () => {
  const file = fileInput.files?.[0]
  if (file) {
    try {
      const response = await client.uploadFile({ file })
      console.log('File uploaded successfully:', response)
    } catch (error) {
      console.error('Upload failed:', error)
    }
  }
}

HTML Example

<input type="file" id="file-input" />

Just select a file, and it will be uploaded to the server using the uploadFile endpoint. With oRPC's type-safe client, both input and output are fully typed, making it simple to handle file uploads effectively.

On this page