Skip to content

[question] How to save a file using formData? #207

Description

@pruge

I tried to save the file as follows:
Next.js + tRPC + FormData

I am unable to proceed further as I am getting the following error:

TRPCClientError: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined",
    "path": [
      "category"
    ],
    "message": "Required"
  },
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined",
    "path": [
      "project"
    ],
    "message": "Required"
  },
  {
    "code": "custom",
    "message": "Input not instance of File",
    "fatal": true,
    "path": [
      "file"
    ]
  }
]
    at y.from (renderer.mjs:135:21)
    at Object.next (renderer.mjs:529:23)
    at ne.v (renderer.mjs:512:21)
    at eval (renderer.mjs:490:21)

Is there an example of how to save the file?

I tried the following:
api.ts

export const UploadFileSchema = zfd.formData({
  category: zfd.text(),
  project: zfd.text(),
  file: zfd.file(),
})
export const GetFileSchema = z.object({
  category: z.string(),
  project: z.string(),
})

export const router = t.router({
  getFiles: t.procedure.input(GetFileSchema).query(async (req) => {
    const { input } = req
    const { category, project } = input
    const filelist = await getFilelist(category, project)
    const assets = await Promise.all(
      filelist.map(async (file) => {
        const type = await getType(file.cwd, file.name)
        // console.log('type', type, file)
        return {
          category: type,
          type,
          src: file.url,
        }
      }),
    )

    return assets as unknown as Asset[]
  }),
  uploadFile: t.procedure.input(UploadFileSchema).mutation(async (req) => {
    console.log('uploadHmiFile', req)
    // const { input } = req
    // const { category, project, file } = input

    // const { cwd, url, name } = await writeFileToDisk(category, project, file)

    // const type = await getType(cwd, name)
    // return {
    //   category,
    //   type,
    //   src: url,
    // }
  }),
})

uploader.tsx

const upload = trpc.uploadFile.useMutation({
    onSuccess() {
      alert('success!')
    },
    onError(err) {
      console.log(err)
    },
  })

  const onDrop = useCallback((acceptedFiles) => {
    try {
      const file = acceptedFiles[0]
      const formData = new FormData()
      formData.append('category', 'hmi')
      formData.append('project', 'test')
      formData.append('file', file)

      for (const pair of formData.entries()) {
        console.log(pair[0] + ', ' + pair[1])
      }

      const dataObject = UploadFileSchema.parse(formData)
      console.log(formData, dataObject)

      upload.mutate(formData)
    } catch (error) {
      console.log(error)
    }
  }, [])
  const { getRootProps, getInputProps } = useDropzone({ onDrop })

console.log, error

category, hmi
project, test
file, [object File]

 FormData {} {category: 'hmi', project: 'test', file: File}

TRPCClientError: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined",
    "path": [
      "category"
    ],
    "message": "Required"
  },
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined",
    "path": [
      "project"
    ],
    "message": "Required"
  },
  {
    "code": "custom",
    "message": "Input not instance of File",
    "fatal": true,
    "path": [
      "file"
    ]
  }
]
    at y.from (renderer.mjs:135:21)
    at Object.next (renderer.mjs:529:23)
    at ne.v (renderer.mjs:512:21)
    at eval (renderer.mjs:490:21)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions