Home > Software engineering >  Posting file upload via AJAX returns empty dictionary on Flask side
Posting file upload via AJAX returns empty dictionary on Flask side

Time:10-25

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.

CodePudding user response:

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)
  • Related