1

I am trying to upload an image within my ReactJS service to my NestJS API service, through my API, but it's not working yet. This is the React code:

First the form:

<div>
 <input type="file" name="urlpromo" value={urlpromo} onChange={this.changeHandler} />
</div>
<button type="submit">Submit</button>

and the functions:

changeHandler = (e) => {
    this.setState({[e.target.name]: e.target.value})
}

submitBaner = (e) => {
        var bodyFormData = new FormData();

        bodyFormData.append('file', this.state.urlpromo);
        
        let config = {
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'multipart/form-data',
              }
        }
        e.preventDefault()
        console.log(bodyFormData)
        axios.post('http://localhost:3000/images/upload', bodyFormData,config)
    }

The thing is that before I was sending images, only with JSON body, it was working fine, but now with form-data, I cant make it work. This is how I can upload an image with Postman:

enter image description here

When I try to make it work, the function console log prints this:

FormData {}__proto__: FormData

What I am doing wrong, how should I work with this form-data?

2
  • Is this working from postman? Commented May 26, 2021 at 7:04
  • Don't try logging the FormData instance, it is not serialisable Commented May 26, 2021 at 7:27

1 Answer 1

1

As per the docs, <input type="file"> is uncontrolled due to its read-only value.

One option is to use a ref to track the <input> element and the files property to access the File

// in your constructor
this.urlPromoRef = React.createRef()
<div>
 <input type="file" ref={this.urlPromoRef} />
</div>
<button type="submit">Submit</button>

and in your submit handler

e.preventDefault()
const bodyFormData = new FormData();
bodyFormData.append('file', this.urlPromoRef.files[0]);

// no need for extra headers
axios.post('http://localhost:3000/images/upload', bodyFormData)

Another option is to simply pass the <form> itself into the FormData constructor.

<form onSubmit={this.submitBaner}>
  <div>
    <input type="file" name="urlpromo" /> <!-- must have a name -->
  </div>
  <button type="submit">Submit</button>
</form>
submitBaner = (e) => {
  e.preventDefault()

  const bodyFormData = new FormData(e.target); // pass in the form

  axios.post('http://localhost:3000/images/upload', bodyFormData)
}

Finally, you may be able to use something like your original code but with a special check for <input type="file">. Eg

changeHandler = (e) => {
  const el = e.target
  this.setState({
    [el.name]: el.type === "file" ? el.files[0] : el.value
  })
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, with the ChangeHandler thing I fixed it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.