Home > Blockchain >  Django & AJAX file upload
Django & AJAX file upload

Time:07-28

When using POST request with AJAX in Django 4.0.1 I can't reach the file from the backend using request.FILES. The form used is pretty simple so I can't spot any typos etc.

HTML:

<form id="snipForm" method="POST" enctype="multipart/form-data">
  {% csrf_token %}
      <input type="file" id="multiFiles" name="files[]" multiple="multiple"/>
      <button id="upload">Upload</button>
</form>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

JavaScript: (sorry for quite a long code sample but I can't shrink it more)

$(document).ready(function (e) {
  $('#upload').on('click', function (event) {
    //Prevent page from reloading
    event.preventDefault()
    var form_data = new FormData();
    // check if there is any file selected
    var ins = document.getElementById('multiFiles').files.length;
    if(ins == 0) {
      $('#msg').html('<span style="color:red">Select at least one file</span>');
      return;
    }
    // add all files
    for (var x = 0; x < ins; x  ) {
      form_data.append("files[]", document.getElementById('multiFiles').files[x]);
    }
    // obtain CSFR token
    csrf_token = $('input[name="csrfmiddlewaretoken"]').val();

    // set the headers
    headers = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest', 'X-CSRFToken': csrf_token};

    $.ajax({
      type: 'POST',
      url: '/docs/', // point to server-side URL
      dataType: "json",
      ContentType: "application/x-www-form-urlencoded",
      cache: false,
      processData: false,
      headers: headers,
      data: form_data,
      success: function (response) { // display success response
        console.log("successssssssssssss")
      },
      error: function (response) {
        console.log("NOPEEEEEE")
      }
    });
  });
});

views.py:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def generate(request):
    is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
    if request.method == 'POST' and is_ajax:
        files = request.FILES.getlist('files[]')
        if files:
            print("file here")
            #do some stuff
        else:
            print("NO FILE AT ALL")
        return JsonResponse({...})

Request itself seems to be working console.log('sucessss') is visible after request is completed. Django however has no access to the file. The data with stored file is saved in the form_data but as far as I know we can reach files through mentioned request.FILES['name_of_the_input'].

What might be the cause?

CodePudding user response:

When doing a file upload(with FormData) with $.ajax, you must set contentType and processData to false.
Otherwise jQuery will try to convert you FormData object to a string and set the content type of the request to "application/x-www-form-urlencoded" which is wrong.
The correct content type is multipart/formdata and will be set automatically.

$.ajax({
  type: 'POST',
  url: '/docs/', // point to server-side URL
  dataType: "json",
  cache: false,
  contentType: false,
  processData: false,
  headers: headers,
  data: form_data,
  success: function (response) { // display success response
    console.log("successssssssssssss")
  },
  error: function (response) {
    console.log("NOPEEEEEE")
  }
});
  • Related