jsonnull / electron-trpc

Build type-safe Electron inter-process communication using tRPC
https://electron-trpc.dev/
MIT License
267 stars 26 forks source link

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

Open pruge opened 2 weeks ago

pruge commented 2 weeks ago

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
```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)