Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FormData support #37

Closed
danielroe opened this issue Dec 13, 2021 · 27 comments
Closed

FormData support #37

danielroe opened this issue Dec 13, 2021 · 27 comments
Labels
enhancement New feature or request needs reproduction

Comments

@danielroe
Copy link
Member

Seems a good idea for using [object FormData] to append proper content-type (adding in short)

Originally posted by @pi0 in #36 (comment)

Other notes:

  • validate formdata content or ensure we're not in browser environment to avoid setting header when sending files/blobs
  • Content-Disposition header
@danielroe danielroe changed the title Add proper headers for FormData Add headers for FormData automatically Dec 13, 2021
@pi0 pi0 changed the title Add headers for FormData automatically FormData support Dec 21, 2021
@jshimkoski
Copy link

Very interested in gaining access to the Content-Disposition header. That is something we need for our project.

@IsraelOrtuno
Copy link

I did not know about Content-Disposition and also I don't really understand why I have to pass the formData variable to body and Content-Disposition header but this seems to work:

const formData = new FormData()

formData.append('avatar', avatar)
formData.append('model', model)
formData.append('id', id)

$fetch('/avatar', {
  method: 'POST',
  body: formData,
  headers: { 'Content-Disposition': formData }
})

@bernlorbis
Copy link

Still a bug in nuxt 3

@nozomuikuta nozomuikuta added the enhancement New feature or request label Jan 11, 2023
@posva
Copy link

posva commented Mar 9, 2023

I think the problem comes from the content-length header. The error happens before sending the request:

  cause: RequestContentLengthMismatchError: Request body length does not match content-length header
      at AsyncWriter.write (node:internal/deps/undici/undici:10139:19)
      at writeIterable (node:internal/deps/undici/undici:10103:23) {
    code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'

Axios seems to be able to send the same exact request

@danielroe
Copy link
Member Author

danielroe commented Mar 9, 2023

@posva We're seeing people encounter issues with undici - do you encounter the same issue if you downgrade y our node version?

Copy link

posva commented Mar 9, 2023

I get the same result with both node 18 and node 16 (latest patchs)

@maximlopin
Copy link

maximlopin commented Mar 30, 2023

I did not know about Content-Disposition and also I don't really understand why I have to pass the formData variable to body and Content-Disposition header but this seems to work:

const formData = new FormData()

formData.append('avatar', avatar)
formData.append('model', model)
formData.append('id', id)

$fetch('/avatar', {
  method: 'POST',
  body: formData,
  headers: { 'Content-Disposition': formData }
})

when I set Content-Disposition to an arbitrary string, it works too

@TusharRoy23
Copy link

TusharRoy23 commented Jul 24, 2023

const formData = new FormData();
const keys = Object.keys(payload);
keys.forEach(key => {
        formData.append(key, payload[key]);
});
$fetch(`/data-imports/`,
      {
        method: 'POST',
        body: formData,
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
    )
      .then(res => {
        console.log(res);
      })
      .catch(error => {
        console.log(error);
      });

Can't send FormData. Any updates?
By the way, I am using it in the Nuxt-2-bridge as the default package.

@TusharRoy23
Copy link

const formData = new FormData();
const keys = Object.keys(payload);
keys.forEach(key => {
        formData.append(key, payload[key]);
});
$fetch(`/data-imports/`,
      {
        method: 'POST',
        body: formData,
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }
    )
      .then(res => {
        console.log(res);
      })
      .catch(error => {
        console.log(error);
      });

Can't send FormData. Any updates? By the way, I am using it in the Nuxt-2-bridge as the default package.

The issue has been resolved after removing the Content-type from the request header and the browser will detect that automatically. And also check in the request header if the Accept: */* is like that or not.

@Hebilicious
Copy link
Member

As mentioned by @TusharRoy23, when using formData, do not specify a 'Content-Type' header, as it will automatically be set by fetch.
@posva do you have a repro for this error 🙏🏽 ?

Copy link

posva commented Aug 8, 2023

I don't have one anymore but should be reproducible (if still there) when trying to send images, something like https://vueuse.org/core/useFileDialog/#usefiledialog.

@TusharRoy23
Copy link

@Hebilicious I don't have. But If you still having this issue then you have to forcefully remove the Content-type from the header.

@geminigeek
Copy link

geminigeek commented Aug 16, 2023

any solution to this, having same issue ,

EDIT: my server had issue , its working fine

@Lukeharris30
Copy link

I am having this issue. I am not setting the content type, but I am setting auth headers.

It keeps sending the content-type as application/json

@sanyaches
Copy link

Meanwhile, Axios works great with this setup without any magic. Just create its instance in nuxt plugin

@jeannen

This comment was marked as off-topic.

@nonomaxxis

This comment was marked as off-topic.

@Idji

This comment was marked as off-topic.

@tewshi
Copy link

tewshi commented Jun 6, 2024

I can confirm from the latest version:

  • do not manually set content-type header, it will be detected and set (with extra things like boundary)
  • no need to set content-disposition manually

Copy link
Member Author

Excellent. If anyone is still experiencing this, please let me know and I'll happily reopen.

@belfortf
Copy link

Hi, using nuxt 3, this doesn't work for me:

const formData = new FormData();
Object.keys(fields).forEach((field) => {
        formData.append(field, fields[field]);
});

formData.append('file', new Blob([JSON.stringify(content)], { type: 'application/json' }));

//Investigate in the future why $fetch doesn't work!!!
const response = await $fetch(url, {
            method: 'POST',
            body: formData
 });

console.log('Response: ',response);

It also doesn't work if I don't specify { type: 'application/json' } for the file.

Any ideas what I should do? My workaround at the moment is to use fetch instead of $fetch.

@maxibue
Copy link

maxibue commented Jun 25, 2024

@belfortf assuming you mean that the form body is not being sent, both JSON and form bodies work fine for me. The content information headers should be set automatically too. Could you provide some code of how you handle the incoming request? Or if the error is something else maybe provide the error?

@hrynevychroman
Copy link

image

I have created ofetch instance to use inside the app. Every API call receives JSON data, but I have one endpoint that needs to send a formData instance. So, I need to manually disable the Content-Type header by setting it to undefined. Everything works, but I receive a typescript error. Maybe we need to extend our type definitions?

image

@gokhantaskan
Copy link

I have encountered a difference in the content type used by $fetch in Nuxt 3 (^3.12.4) compared to the native fetch and ofetch methods.

Specifically, $fetch utilizes application/json with Form Data, while the native fetch and ofetch methods use multipart/form-data; boundary=----WebKitFormBoundarySOMETHING. I'm curious to understand the reason behind this difference.

@danielroe
Copy link
Member Author

@gokhantaskan $fetch is created with ofetch and should not differ (except perhaps in internal requests, which are powered by unenv) so I would be grateful of a reproduction and new issue if you are happy to make one.

@gokhantaskan
Copy link

@gokhantaskan $fetch is created with ofetch and should not differ (except perhaps in internal requests, which are powered by unenv) so I would be grateful of a reproduction and new issue if you are happy to make one.

I noticed an issue with the $api implementation at the following URL, https://nuxt.com/docs/guide/recipes/custom-usefetch#custom-fetch. It seems that $fetch.create might be causing the problem. I don't have time to reproduce it right now, but I will attempt to do so tomorrow.

Tested with ofetchand $fetchdirectly in my Nuxt codebase, it automatically added the Content-Type header.

@gokhantaskan
Copy link

I've identified the issue, and it's on my end:

const $api = $fetch.create({
      baseURL: config.public.apiPath,
      credentials: "include",
      // Convert request body to snake_case
      onRequest({ options }) {
        if (options.body) {
          options.body = changeObjectKeysCase(options.body, "snake");
          ^^^ This line manipulates FormData and makes it plain object
        }
      },
...

I solved it with the following code:

onRequest({ options }) {
  if (options.body) {
    if (options.body instanceof FormData) {
      const formData = new FormData();

      for (const [key, value] of options.body.entries()) {
        formData.append(snakeCase(key), value);
      }

      options.body = formData;
    } else {
      options.body = changeObjectKeysCase(options.body, "snake");
    }
  }
},

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs reproduction
Projects
None yet
Development

No branches or pull requests