Pregunta

I'm trying to upload multiple pictures with javascript. I was able to get one picture to upload fine - but when I upload n pictures, it just uploads the first picture of the group n times. The code is as follows:

var field = document.getElementById('file-field')

field.addEventListener('change', function(data) {
  var files  = data.target.files

  for(var i=0; i<files.length; i++) {
    multipartPost('/photos/create', files[i]) // I've tried moving this out into another function, an IIFY, etc
  }
})

function multipartPost(url, params, callback) {
  var xml  = new XMLHttpRequest()
  var data = new FormData()
  data.append('file', params, false) // This is where I fixed it so it can at least upload synchronously by passing false as a third param

  xml.open('post', url)
  xml.send(data)

  xml.onreadystatechange = function() {
    if(xml.readyState===4) {
      if(xml.status===200) {
        console.log('success')
      } else {
        console.log(xml.status, "Error")
      }
    }
  }
}

Any idea on how to get it to upload ALL the pictures or why its repeatedly uploading the single picture n times?


A little more background:

I originally had a form which I would submit to upload a file, but then I decided to get it to upload through javascript. Turns out that it's really simple with XHR2, and I was able to successfully upload a file without a form - the html is simply

<input type="file" name="file" id="file-field" multiple />

However I decided to go to the next step and allow multiple uploads. I thought it would be as simple as changing files[0] to files[i] inside a for loop, but if I upload multiple files, it just takes the first file and uploads it n times, n being the amount of files that are in the file field.


Update

I was able to get the multiple file uploads using synchronous post requests, by passing a third parameter of value false to the function XMLHttpRequest.open, so there is definitely an error related to a-sync. I'll keep debugging but if anyone knows why it's not working asynchronously I'm very curious


Solution

var field = document.getElementById('file-field')

field.addEventListener('change', function(e) {
  var files  = e.target.files
  for(var i = 0; i < files.length; i++) {
    multipartPost('/photos/create', files[i], appendPhoto)
  }
})

function appendPhoto(data) {
  // Callback function
}

function multipartPost(url, params, callback) {
  var xml  = new XMLHttpRequest()
  var data = new FormData() // Using FormData allows me to keep my server-side code the same, just as if it were a form submission
  data.append('file', params)

  xml.open('post', url) // No third param will default to async: true
  xml.setRequestHeader("X-Requested-With","XMLHttpRequest") // This header allows me to recognize the request as xhr server side
  xml.send(data)

  xml.onreadystatechange = function() {
    if(xml.readyState===4) {
      if(xml.status===200) {
        callback(xml.responseText)
      } else {
        console.log(xml.status, "Error")
      }
    }
  }
}
¿Fue útil?

Solución 2

There was actually an async error saving to the database server-side - the above code works. However, after opening the request you do have to set a header if you want to be able to recognize it as xhr. The header you have to set is below, but I updated the code to be the final code I'm working with in my question above:

xml.setRequestHeader("X-Requested-With","XMLHttpRequest")

Otros consejos

Code seems to be incorrect. Maybe after manual editing while posting: look at the for loop. There is "i" variable declared and used while inside the loop you use "index" variable. Also I see no callback param given. I am not sure that anything here is related to closure. What are you going to do with the help of this code?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top