Skip to content
Advertisement

Posting file upload via AJAX returns empty dictionary on Flask side

I have a Flask app that was working until I added login functionality. The issue I’m having is I have a modal that the user can upload a file with.

HTML

<p>Upload Photo</p>
          <form method="POST" name="upload_pic" id="upload_pic" enctype="multipart/form-data">
          <input type="file" class="custom-file-input" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
          <label class="custom-file-label" for="exampleInputFile">
           Select file...
        </label>
            <button type="button" class="btn btn-success" data-dismiss="modal" id="AddNotesSubmit">Submit</button>

Then an AJAX call to upload the file:

// add notes post
  $('#AddNotesSubmit').on('click', function(e) {

      var notes = $("#note_text").val();
      var schedule_id = $("#noteSchID").text();

      console.log(notes);

      e.preventDefault();
      $.ajax({
          type: "POST",
          url: "/",
          data: { AddNotes: "", schedule_id: schedule_id, notes: notes },
          success:function(response){
             $('#response').text(JSON.stringify(response));
          }
      });

      var fullPath = $("#exampleInputFile").val();
      var filename = fullPath.replace(/^.*[\/]/, '');
      const form = $('#upload_pic')[0];
      const pic = new FormData(form);

      console.log(form);
      console.log(pic);
      console.log(filename);

      if (filename != '') {
        $.ajax({
            type: "POST",
            url: "/upload_pic",
            data: pic,
            processData: false,  // tell jQuery not to process the data
            contentType: false   // tell jQuery not to set contentType
        });
      }


      $('#modalAddNotes').modal('hide');
  });

  });

And finally the Flask code I’m using to debug:

@app.route('/upload_pic', methods=['POST'])
def upload_pic():
        print(' request.files: %s' %request.files)
        files = request.files.get('files[]')
        print(' files: %s' %files)

The command line output on the python side is:

request.files: ImmutableMultiDict([])
files: None

So it’s returning an empty dictionary. Previously, when I used:

uploaded_pic = request.files['exampleInputFile']

It worked, but now with that code included it throws a 400 error because the 'exampleInputFile' is invalid key in the request.files dictionary. I removed the @login_required from the route and it didn’t change anything.

Advertisement

Answer

From my point of view, it is difficult to see why your code is not working. In your example, the form tag is not closed. Also, you didn’t describe how your javascript code is executed. Although I assume that you are using a click event, I tested your code with a submit event. I have come to the conclusion that the code works.

Here is the variant I used for testing:

  <p>Upload Photo</p>
    <form method="POST" name="upload_pic" id="upload_pic" enctype="multipart/form-data">
      <input type="file" class="custom-file-input" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
      <label class="custom-file-label" for="exampleInputFile">
       Select file...
      </label>
      <button type="submit" class="btn btn-success" data-dismiss="modal" id="AddNotesSubmit">Submit</button>
    </form>

    <script
      src="https://code.jquery.com/jquery-3.6.0.min.js"
      integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
      crossorigin="anonymous"></script>
    <script type="text/javascript">
      $(document).ready(function() {
        $('form[name="upload_pic"]').submit(function(event) {
          event.preventDefault();
          const form = event.target;
          const formData = new FormData(form);
          $.ajax({
            type: 'POST',
            url: '/upload_pic',
            data: formData,
            processData: false,
            contentType: false
          }).done((data) => {
            console.log(data);
          })
        });
      });
    </script>
@app.route('/upload_pic', methods=['POST'])
def upload_pic():
    if 'exampleInputFile' in request.files:
        file = request.files['exampleInputFile']
        if file.filename != '':
            # handle file here!
            return jsonify(success=True)
    return jsonify(success=False)
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement