trpc to upload file

1.1k views Asked by At

I am making a web app using NextJS with TRPC. In my app I have a form that asks to select a File. What I need to do is pass the file a trpc call so I can do all the file logic in the backend and not in the front end, because I am going to make API requests and I am on a "use client" page. This is the code I have:

"use client"

import * as z from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "../ui/form"
import { Button } from "../ui/button"
import { Input } from "../ui/input"
import { trpc } from "@/app/_trpc/client"

const TrainForm = () => {

  const formSchema = z.object({
    file: z.instanceof(File)
  })

  const { mutate: uploadFile, isLoading } = trpc.uploadFile.useMutation()

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema)
  })

  function onSubmit(data: z.infer<typeof formSchema>) {
    console.log(data.file)

    // Handle file
uploadFile({
  file: data.file
})
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className=" space-y-4 p-8">

        <FormField
          control={form.control}
          name="file"
          render={({ field }) => (
            <Input accept="application/pdf" type="file" name="file" onChange={(e: any) => {
              const file = e.target.files?.[0]
              field.onChange(file)
            }} />
          )}
        />

        <Button disabled={isLoading} type="submit">
          Submit
        </Button>
      </form>
    </Form>
  );
}

export default TrainForm;

TRPC:

import { privateProcedure, publicProcedure, router } from './trpc';
import { TRPCError } from '@trpc/server'
import { db } from '@/db';
import { z } from 'zod';

export const appRouter = router({
    // query to get data
    // mutation to modify data


    // Private
    uploadFile: publicProcedure.input(z.object({
      file: z.instanceof(File)
    })).mutation(async ({input}) => {

      // handle file
    }),

  });

// Export type router type signature,
// NOT the router itself.
export type AppRouter = typeof appRouter;

Errors:

[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (uploadFile, line 0)
[Error] TRPCClientError: The string did not match the expected pattern.
    (anonymous function) (app-index.js:32)
    (anonymous function) (hydration-error-info.js:41)
    (anonymous function) (mutation.mjs:167)

Thanks!!!

2

There are 2 answers

0
John On

Passing a file to tRPC is not supported yet. You can use FormData, currently in experimental phase.

0
Kygo On

To pass a File in zod use.

z.custom<File>();