16

I have an uploader that allows a user to upload several pictures. In order to only create or update the images he wants to add/change, I update an object that looks like this:

{main: Blob, "1": Blob, "2":Blob}

So if only needs to update "1" later, the sent object will only contain {"1": Blob}

When clicking on save, it triggers a function that is supposed to append the images to a formData(). Sadly the formData is never updated. I have the following error:

Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'.

export async function uploadImages(files, userId) {
  try {
    const images = new FormData();
    files.main && images.append("image", files.main, "main");
    files[1] && images.append("image", files[1], "1");
    files[2] && images.append("image", files[2], "2");

    const res = await ax.post(process.env.SERVER_URL + "/upload-images", {
      images,
      userId,
    });
    return "success"
  } catch (err) {
    return "error"
  }
}

How to fix this? Thanks!

4 Answers 4

3

You should not be able to see FormData object contents in console, because its not serializable. You can check request payload instead, check "Network" tab in your browser dev tools, find your request and look at the bottom of "Headers" tab to see "FormData" log. You will see something like this: enter image description here

Also, you should set header "Content-Type" to "multipart/form-data" in axios. Here is working example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <input type="file" multiple id="filepicker" />

    <button id="send">Send</button>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.20.0/axios.min.js"></script>
    <script>
      const myformData = new FormData();

      document
        .querySelector('#filepicker')
        .addEventListener('change', function (event) {
          const { files } = event.target;

          Object.values(files).forEach(function (file, index) {
            myformData.append(index, file);
          });
        });

      document.querySelector('#send').addEventListener('click', function () {
        axios({
          method: 'post',
          url: 'http://google.com',
          data: myformData,
          headers: { 'Content-Type': 'multipart/form-data' },
        })
          .then((response) => console.log(response))
          .catch((err) => console.log(err));
      });
    </script>
  </body>
</html>

Sign up to request clarification or add additional context in comments.

7 Comments

I actually log the images formData when when receiving the request in my node server. I thought I could see it through req.body.images. By doing your method, I receive the error "Error: Multipart: Boundary not found at new Multipart".
I just checked and it works. If you are using Node.js and Express, then you probably missing middleware for handling file uploads, check this answer
But I already have bodyparser and multer to handle data parsing, do I need to install busboy as well?!
If you already have multer, then you dont need to install busboy (since multer uses busboy as a dependency). It means that there is something wrong with your code logic. You can use code snippet from the answer I linked above, or create a new question, since backend logic is not related to FormData question.
Ok I've finally found the mistake: I was trying to access the data through req.body and not req.file... It works now. However, I still need to send the user id as well in the same post request. Would you know how to do it?
|
3

I faced this issue on my react native app. To solve it I had to convert the image path to a blob. The code for my handle upload function is given below.

const handleUpload = async () => {
    if (selectedImage.localUri !== '') {

        const image_uri =  Platform.OS === 'ios' ? selectedImage.localUri.replace('file://', '') : selectedImage.localUri;

        const response = await fetch(image_uri);
        const blob = await response.blob();

        const formData = new FormData();
        formData.append('image', blob, "xray_image.jpg");
  
        setLoading(true);

        axios.post("https://...", formData)
            .then((result) => {
               console.log(result);
            })
            .catch((err) => {
                console.log(err);
              
            });

    } else {
        console.log("Select a file error message");
    }
};

Comments

0
export async function uploadImages(files, userId) {
  try {
    const images = new FormData();
    for(const file of files){
        images.append("image", file);
    }
    const res = await ax.post(process.env.SERVER_URL + "/upload-images", {
      images,
      userId,
    });
    return "success"
  } catch (err) {
    return "error"
  }
}

1 Comment

The formData is still empty.
-4

you have to pass the extension along with the name

files[1] && images.append("image", files[1], "custom-name.jpg");

Comments

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.