3

What I am trying to achieve is to send a request from the Client Side (React) to the Server Side (Express) containing the uploaded image file

Here an example of a form I created on the Server which sends the data I should be sending with React instead:

<form method="post" action="post" enctype="multipart/form-data">
  <input type="file" name="image" /><br /><br />
  <button type="submit" name="upload">Upload</button>
</form>

This is the object sent by the submitted form when uploaded an image: link

Here the React Component:

const Component = () => {
  const setImageAction = async (event) => {
    event.preventDefault();

    const data = await fetch("http://localhost:3000/upload/post", {
      method: "post",
      headers: { "Content-Type": "multipart/form-data" },
      body: JSON.stringify({

      }),
    });
    const uploadedImage = await data.json();
    if (uploadedImage) {
      console.log('Successfully uploaded image');
    } else {
      console.log('Error Found');
    }
  };

  return (
    <div className="content">
      <form onSubmit={setImageAction}>
        <input type="file" name="image" />
        <br />
        <br />
        <button type="submit" name="upload">
          Upload
        </button>
      </form>
    </div>
  );
};

As you can see, in the React Component the body request is empty as I haven't figured out how to retrieve that file object..

Thank you in advance for your help!

EDIT

Updated as shown, with the only difference of keeping State as Hook

Here the new React Component Code:

const LandingPage = () => {
  const [picture, setPicture] = useState({});

  const uploadPicture = (e) => {
    setPicture({
      /* contains the preview, if you want to show the picture to the user
           you can access it with this.state.currentPicture
       */
      picturePreview: URL.createObjectURL(e.target.files[0]),
      /* this contains the file we want to send */
      pictureAsFile: e.target.files[0],
    });
  };

  const setImageAction = async (event) => {
    event.preventDefault();

    const formData = new FormData();
    formData.append("file", picture.pictureAsFile);

    console.log(picture.pictureAsFile);

    for (var key of formData.entries()) {
      console.log(key[0] + ", " + key[1]);
    }

    const data = await fetch("http://localhost:3000/upload/post", {
      method: "post",
      headers: { "Content-Type": "multipart/form-data" },
      body: formData,
    });
    const uploadedImage = await data.json();
    if (uploadedImage) {
      console.log("Successfully uploaded image");
    } else {
      console.log("Error Found");
    }
  };

  return (
    <div className="content landing">
      <form onSubmit={setImageAction}>
        <input type="file" name="image" onChange={uploadPicture} />
        <br />
        <br />
        <button type="submit" name="upload">
          Upload
        </button>
      </form>
    </div>
  );
};

And here what I get from those console.logs: link

I created a snippet in codesandbox if you want to have a look at: https://codesandbox.io/s/heuristic-snyder-d67sn?file=/src/App.js

1 Answer 1

6

add this method to capture the onChange event :

add 2 properties to your state : picturePreview and pictureAsFile

uploadPicture = (e) => {
        this.setState({
            /* contains the preview, if you want to show the picture to the user
               you can access it with this.state.currentPicture
           */
            picturePreview : URL.createObjectURL(e.target.files[0]),
            /* this contains the file we want to send */
            pictureAsFile : e.target.files[0]
        })
    };

now, on your onSubmit event :

setImageAction = () => {
        const formData = new FormData();
        formData.append(
            "file",
            this.state.pictureAsFile
        );
        // do your post request

    };

of course don't to add the uploadPicture method to your input:

 <input type="file" name="image" onChange={this.uploadPicture}/>

EDIT

to display your formData :

for (var key of formData.entries()) 
{
    console.log(key[0] + ', ' + key[1])
}
Sign up to request clarification or add additional context in comments.

9 Comments

I followed your example and I can now display the file uploaded accessing pictureAsFile; Only problem is the formData.append doesn't work. If I tried to display it I get an empty object; Any idea why?
well FormData is a special object, that cannot be displayed using console.log
also, its not stringifyable, so th body must contain directly your FormData
i've added a way to log your dataForm content
Sorry for not replying, totally forgot. Anyway I found the problem keep looking on the net, and found to be the headers: { "Content-Type": "multipart/form-data" } that didn't have to be set when uploading files. By just removing that line of code I solved the issue. Your comment helped me a lot though.
|

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.