Upload Image Request from React

13,217

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])
}
Share:
13,217

Related videos on Youtube

ale917k
Author by

ale917k

I love helping people and solve problems

Updated on June 04, 2022

Comments

  • ale917k
    ale917k almost 2 years

    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

  • ale917k
    ale917k almost 4 years
    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?
  • Djellal Mohamed Aniss
    Djellal Mohamed Aniss almost 4 years
    well FormData is a special object, that cannot be displayed using console.log
  • Djellal Mohamed Aniss
    Djellal Mohamed Aniss almost 4 years
    also, its not stringifyable, so th body must contain directly your FormData
  • Djellal Mohamed Aniss
    Djellal Mohamed Aniss almost 4 years
    i've added a way to log your dataForm content
  • ale917k
    ale917k almost 4 years
    I've updated as you suggested; Please see codesandbox for details
  • Djellal Mohamed Aniss
    Djellal Mohamed Aniss almost 4 years
    can you show your server-side code? you're getting a 500 error code so maybe the issue is in express
  • ale917k
    ale917k almost 4 years
    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.
  • Djellal Mohamed Aniss
    Djellal Mohamed Aniss almost 4 years
    No problem. Good luck