Search code examples
javascriptvue.jsaxiosform-data

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


i'm trying to upload multiple images in vue

this the response i get after uploading the multiple files

{
    "0": {},
    "1": {}
}

this is my input tag

<input
  type="file"
  @change="onFileSelected"
  multiple
  ref="files"
/>

this is my function

export default {
  data() {
    return {
      selectedFile: null,
      stockQuantity: 1,
      fileName: "",
      photos: null,
    };
  },
  methods: {
    onFileSelected(event) {
      this.selectedFile = event.target.files;
      console.log(this.selectedFile);
      this.fileName = event.target.files.name;
    },
    async onAddProduct() {
      // POST request using axios with async/await
      let data = new FormData();
      for (const i of Object.keys(this.selectedFile)) {
        data.append(
          "photos",
          photos[i],
          this.selectedFile,
          this.selectedFile[i]
        );
      }
      const response = await axios
        .post("http://localhost:5000/api/products", data, {
          headers: { "Content-Type": "multipart/form-data" },
        })
        .then((response) => {
          console.log(response);
          // this.$router.push('/')
        });
    },
  },
};

i get both images but when i click on onAddProduct i get

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


Solution

  • There are several problems here...

    1. event.target.files is a collection. It does not have a name property. Also, if you're uploading multiple files there's no point storing a single filename.
    2. photos is never populated and doesn't appear to serve any purpose
    3. FormData.append() accepts at most 3 parameters, not 4 and you probably only need 2.
    4. Axios knows what to do with FormData, you do not need to customise the content-type header.

    Really all you need for this is the following...

    export default {
      data() {
        return {
          selectedFiles: [], // plural
        };
      },
      methods: {
        onFileSelected(event) {
          this.selectedFiles = event.target.files;
        },
        async onAddProduct() {
          const data = new FormData();
    
          // loop over selectedFiles and append
          for (const file of this.selectedFiles) {
            data.append("photos", file);
          }
    
          // no custom headers required
          const response = await axios.post(
            "http://localhost:5000/api/products",
            data
          );
    
          console.log(response);
          // this.$router.push('/')
        },
      },
    };