honojs / hono

Web framework built on Web Standards
https://hono.dev
MIT License
18.14k stars 509 forks source link

Uploading a file using FormData from React Native to Hono #3141

Open AssafFogelman opened 1 month ago

AssafFogelman commented 1 month ago

What version of Hono are you using?

4.4.13

What runtime/platform is your app running on?

NodeJs

What steps can reproduce the bug?

in Hono:

` user.post("/test", test)

async function test (c:Context){ try { const data = await c.req.formData(); return c.json({message:"formData was sent successfully!"}); } catch (error) { console.log(error); return c.json({message:"error uploading formData", error}) }}`

in React Native (Expo):

`useEffect(() => { (async () => { try { // Load the asset const asset = Asset.fromModule(require('../assets/tilk_icon.png')); await asset.downloadAsync(); // Create FormData const formData = new FormData(); //append a file formData.append('file', { uri: asset.uri, name: 'tilk-icon.png', type: 'image/png' } as any); //append a text formData.append("text", JSON.stringify({message: "hi!"}));

        //send
        const {data} = await axios.post("user/test", formData,{headers:{
          "content-type": 'multipart/form-data; boundary=--------------------------585591568098780255545610'
          }});

        console.log(data)

      } catch (error) {
        console.error('Error creating FormData (response):', error.response);
        console.error('Error creating FormData (request):', error.request);
      }
    })()
  },
  [])`

image

image

What is the expected behavior?

the React Native app should get the URI of an image file called "tilk_icon.png" that is in the "assets" folder.

Then, It should create a FormData and append that file. It also should append a text entry.

Then it should send it to the server using Axios.

The Hono server should receive the request, parse the FormData, and return the object: {message:"formData was sent successfully!"}

What do you see instead?

I see an error in the back-end: TypeError: Failed to parse body as FormData. at node:internal/deps/undici/undici:5410:27 at successSteps (node:internal/deps/undici/undici:5454:27) at fullyReadBody (node:internal/deps/undici/undici:4381:9) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async consumeBody (node:internal/deps/undici/undici:5463:7) at test (C:\programming\_chat_app\chat-app\backend-server\src\routes\user\user.ts:49:18) at async dispatch (file:///C:/programming/_chat_app/chat-app/backend-server/node_modules/hono/dist/compose.js:29:17) at async cors2 (file:///C:/programming/_chat_app/chat-app/backend-server/node_modules/hono/dist/middleware/cors/index.js:70:5) at async dispatch (file:///C:/programming/_chat_app/chat-app/backend-server/node_modules/hono/dist/compose.js:29:17) at async logger2 (file:///C:/programming/_chat_app/chat-app/backend-server/node_modules/hono/dist/middleware/logger/index.js:37:5)

If I remove the manual addition of the header, Axios gives the following error:

"content-type": "application/x-www-form-urlencoded" and "_response": "multipart != application/x-www-form-urlencoded"

meaning, axios sends the FormData in the wrong "content-type".

Additional information

using the "c.req.parseBody()" method, returns the same result.

appending on the text, returns the same result.

marcosrjjunior commented 1 month ago

hey @AssafFogelman , not sure if that is direct related to Hono, but I faced the same issue in the past.

on that I'm using a formData request with rn-fetch-blob dependency.


const body = [
  { name: 'name', data: 'name value' },
  { name: 'other_field', data: 'another value' },
  {
    name: 'file_example',
    filename: 'filename.jpg',
    type: 'image/jpg',
    data: filepath.replace('file:///', 'RNFetchBlob-file://'),
    // having the RNFetchBlob as a prefix is important, have a look on other examples on the link bellow.
  },
]

const headers = {}
const url = ''

await RNFetchBlob.fetch('POST', url, headers, body)

Reference multiform-data

EdamAme-x commented 1 month ago

Could you please show us a capture (console.log) of the request coming to the server side?

kbrandwijk commented 1 month ago

Which RN version are you on? This used to work fine for me with RN 0.73, but broke after upgrading to RN 0.74.