-1

I'm having problems with ajax and flask connection when sending a FormData in a request.

I'm trying to send an array of files from javascript with ajax:

dropArea.addEventListener("drop", (event)=>{
  event.preventDefault(); //preventing from default behaviour
  file = getDroppedOrSelectedFiles(event);

  file.then((value) => {
      res = []
      for (var v in value) {
          console.log(value[v].fileObject)
          res.push(value[v].fileObject)
      }
      var fd = new FormData();
      fd.append("file[]", res.serialize())
      for (var value of fd.values()) {
        console.log(value);
    }
      var req = {
          url: "/upload.html",
          method: "post",
          processData: false,
          data : fd
      };

      var promise = $.ajax(req);
  });

});

And just read this list of files in flask. I've tried with files = request.form.getlist("files[]") but I only receive an empty list. Investigating I've discovered that if I convert request.form into a dictionary the files are actually there but neither the key corresponds to "file[]" nor the values to the files.

dict_items([('-----------------------------110480676136716695933348531592\r\nContent-Disposition: form-data; name', '"file[]"\r\n\r\n[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],[object File],,[object File]\r\n-----------------------------110480676136716695933348531592--\r\n')])

Does anyone know how can I solve it and obtain the list of files?

1 Answers1

0

You can't serialize File objects. You have to put the object itself in the FormData, and then the file contents will be sent in the AJAX request.

dropArea.addEventListener("drop", (event) => {
  event.preventDefault();
  file = getDroppedOrSelectedFiles(event);

  file.then((value) => {
    var fd = new FormData();
    value.forEach(file => {
      console.log(file.name);
      fd.append("file[]", file);
    for (var v in value) {
      console.log(value[v].fileObject)
      fd.append("file[]", value[v].fileObject)
    }
    var req = {
      url: "/upload.html",
      method: "post",
      processData: false,
      contentType: false,
      data: fd
    };

    var promise = $.ajax(req);
  });

});
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • If I put the append inside the for loop, now the dictionary has 400000 keys instead of just one. Should it be like that? – Naxel100 May 07 '21 at 16:42
  • That sounds like a problem with your `getDroppedOrSelectedFiles` function, it should only return the files that have been selected. – Barmar May 07 '21 at 17:32
  • Is there a property in your objects that indicates whether the file has been selected there? You can add an `if` statement to check that. – Barmar May 07 '21 at 17:33
  • The number of keys in the dictionary is the same number as the number of files in the selected folder. It seems as if the append is creating several (key, value) pairs (with some strange key name) instead of creating a DataForm with (key = "files[]", value = list of files). – Naxel100 May 07 '21 at 17:38
  • That's the way it's supposed to work. You can't put arrays directly into FormData. – Barmar May 07 '21 at 17:39
  • If you're uploading 400,000 files, then there will be that many keys in the FD. – Barmar May 07 '21 at 17:40
  • So, is there any way to retrieve the list of files in flask? – Naxel100 May 07 '21 at 17:51
  • `flask.request.files.getlist("file[]")` See https://stackoverflow.com/questions/11817182/uploading-multiple-files-with-flask – Barmar May 07 '21 at 17:54
  • Hi, thank you for your answer. I think the problem is much more difficult than I expected. What I want is to be able to work with those files in flask. The problem is that when I send the files in ajax with the previous code I get the data through request.form in flask instead of request.files. As I can see, request.form is not prepeared to fet files so what I get in flask is completely rubbish. What I should do is to pass the data through request.files but I can't create a fileList so I think it is impossible to solve the problem. – Naxel100 May 08 '21 at 19:14
  • I just noticed that my answer had incomplete code `fd.append("file[]", value[)`. What did you correct that to when you tried it? I think it should be `fd.append("file[]", value[v].fileObject)`, but I'm just guessing what `fileObject` really is in your application. – Barmar May 08 '21 at 19:17
  • Yes, I supposed that and completed it just as you said. fileObject is the javascript file object itself. I should append those files in request.files but I can't do that because it is not possible to create a fileList object. – Naxel100 May 08 '21 at 21:42
  • If you have a `FileList` object that comes from `input.files`, you need to loop over its contents to get all the `File` objects. If `value[v].fileObject` is a `FileList`, you could put that nested loop in this code. – Barmar May 10 '21 at 15:33