Categories
ajax file-upload javascript jquery post

jQuery Ajax File Upload

838

Can I use the following jQuery code to perform file upload using POST method of an ajax request ?

$.ajax({
    type: "POST",
    timeout: 50000,
    url: url,
    data: dataString,
    success: function (data) {
        alert('success');
        return false;
    }
});

If it is possible, do I need to fill data part? Is it the correct way? I only POST the file to the server side.

I have been googling around, but what I found was a plugin while in my plan I do not want to use it. At least for the moment.

3

637

File upload is not possible through AJAX.
You can upload file, without refreshing page by using IFrame.
You can check further details here.


UPDATE

With XHR2, File upload through AJAX is supported. E.g. through FormData object, but unfortunately it is not supported by all/old browsers.

FormData support starts from following desktop browsers versions.

  • IE 10+
  • Firefox 4.0+
  • Chrome 7+
  • Safari 5+
  • Opera 12+

For more detail, see MDN link.

8

  • 44

    Here is a list of the specific browsers that are not supported: caniuse.com/#search=FormData Also I have not tested this but here is a polyfill for FormData gist.github.com/3120320

    Oct 3, 2012 at 0:34


  • 166

    Specifically, IE < 10 doesn’t, for those too lazy to read the link.

    – Kevin

    Nov 1, 2012 at 5:28

  • 25

    @Synexis no we don’t have to wait that long any more because all IE only has a 22% world wide market share and 27% in the U.S. and dropping fast. Chances are it is people over 70 years old. So rather then IE dictating what developers have to do IE will either have to shape up or get out of the race.

    Mar 6, 2014 at 8:49

  • 34

    @DrewCalder Most IE users are office workers who don’t have the choice on which browser to use because of company policies. I don’t think age has much to do with it. I’m guessing most people > 70 get their offspring to install Chrome or FF instead 🙂

    Jun 18, 2014 at 4:10

  • 4

    This link really helped me in understanding the bare minimum. I didn’t have to use a xhr request. If you do use ajax make sure to set the enctype to "form/multipart"!

    – Luminous

    Jul 29, 2015 at 20:54


372

Iframes is no longer needed for uploading files through ajax. I’ve recently done it by myself. Check out these pages:

Using HTML5 file uploads with AJAX and jQuery

http://dev.w3.org/2006/webapi/FileAPI/#FileReader-interface

Updated the answer and cleaned it up. Use the getSize function to check size or use getType function to check types.
Added progressbar html and css code.

var Upload = function (file) {
    this.file = file;
};

Upload.prototype.getType = function() {
    return this.file.type;
};
Upload.prototype.getSize = function() {
    return this.file.size;
};
Upload.prototype.getName = function() {
    return this.file.name;
};
Upload.prototype.doUpload = function () {
    var that = this;
    var formData = new FormData();

    // add assoc key values, this will be posts values
    formData.append("file", this.file, this.getName());
    formData.append("upload_file", true);

    $.ajax({
        type: "POST",
        url: "script",
        xhr: function () {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) {
                myXhr.upload.addEventListener('progress', that.progressHandling, false);
            }
            return myXhr;
        },
        success: function (data) {
            // your callback here
        },
        error: function (error) {
            // handle error
        },
        async: true,
        data: formData,
        cache: false,
        contentType: false,
        processData: false,
        timeout: 60000
    });
};

Upload.prototype.progressHandling = function (event) {
    var percent = 0;
    var position = event.loaded || event.position;
    var total = event.total;
    var progress_bar_id = "#progress-wrp";
    if (event.lengthComputable) {
        percent = Math.ceil(position / total * 100);
    }
    // update progressbars classes so it fits your code
    $(progress_bar_id + " .progress-bar").css("width", +percent + "%");
    $(progress_bar_id + " .status").text(percent + "%");
};

How to use the Upload class

//Change id to your id
$("#ingredient_file").on("change", function (e) {
    var file = $(this)[0].files[0];
    var upload = new Upload(file);

    // maby check size or type here with upload.getSize() and upload.getType()

    // execute upload
    upload.doUpload();
});

Progressbar html code

<div id="progress-wrp">
    <div class="progress-bar"></div>
    <div class="status">0%</div>
</div>

Progressbar css code

#progress-wrp {
  border: 1px solid #0099CC;
  padding: 1px;
  position: relative;
  height: 30px;
  border-radius: 3px;
  margin: 10px;
  text-align: left;
  background: #fff;
  box-shadow: inset 1px 3px 6px rgba(0, 0, 0, 0.12);
}

#progress-wrp .progress-bar {
  height: 100%;
  border-radius: 3px;
  background-color: #f39ac7;
  width: 0;
  box-shadow: inset 1px 1px 10px rgba(0, 0, 0, 0.11);
}

#progress-wrp .status {
  top: 3px;
  left: 50%;
  position: absolute;
  display: inline-block;
  color: #000000;
}

13

  • 4

    You can more or less copy the code straight off and use it. Just change some id names and class names. Any customation is on your own.

    Jun 14, 2012 at 12:49

  • 4

    Note that myXhr seems to be global as well as name, size and type. Also it’s better to use “beforeSend” to augment the already created XMLHttpRequest object rather than using “xhr” to create one then change it.

    – awatts

    Aug 10, 2012 at 9:13


  • 8

    I don’t think we can use that as is @Ziinloader. You’re using some local method that’s not included: writer(catchFile). What is writer()?

    May 21, 2013 at 11:30

  • 4

    What if the data also contains few fields along with file to upload?

    – raju

    Apr 29, 2014 at 18:33

  • 4

    @Ziinloader This is a tremendously useful example that I see you’ve come back to and maintained several times. Truly an answer worth much more than the one upvote I can give.

    Oct 10, 2017 at 21:39

247

Ajax post and upload file is possible. I’m using jQuery $.ajax function to load my files. I tried to use the XHR object but could not get results on the server side with PHP.

var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);

$.ajax({
       url : 'upload.php',
       type : 'POST',
       data : formData,
       processData: false,  // tell jQuery not to process the data
       contentType: false,  // tell jQuery not to set contentType
       success : function(data) {
           console.log(data);
           alert(data);
       }
});

As you can see, you must create a FormData object, empty or from (serialized? – $('#yourForm').serialize()) existing form, and then attach the input file.

Here is more information:
How to upload a file using jQuery.ajax and FormData
Uploading files via jQuery, object FormData is provided and no file name, GET request

For the PHP process you can use something like this:

//print_r($_FILES);
$fileName = $_FILES['file']['name'];
$fileType = $_FILES['file']['type'];
$fileError = $_FILES['file']['error'];
$fileContent = file_get_contents($_FILES['file']['tmp_name']);

if($fileError == UPLOAD_ERR_OK){
   //Processes your file here
}else{
   switch($fileError){
     case UPLOAD_ERR_INI_SIZE:   
          $message="Error al intentar subir un archivo que excede el tamaño permitido.";
          break;
     case UPLOAD_ERR_FORM_SIZE:  
          $message="Error al intentar subir un archivo que excede el tamaño permitido.";
          break;
     case UPLOAD_ERR_PARTIAL:    
          $message="Error: no terminó la acción de subir el archivo.";
          break;
     case UPLOAD_ERR_NO_FILE:    
          $message="Error: ningún archivo fue subido.";
          break;
     case UPLOAD_ERR_NO_TMP_DIR: 
          $message="Error: servidor no configurado para carga de archivos.";
          break;
     case UPLOAD_ERR_CANT_WRITE: 
          $message="Error: posible falla al grabar el archivo.";
          break;
     case  UPLOAD_ERR_EXTENSION: 
          $message="Error: carga de archivo no completada.";
          break;
     default: $message="Error: carga de archivo no completada.";
              break;
    }
      echo json_encode(array(
               'error' => true,
               'message' => $message
            ));
}

9

  • 2

    What jquery library do i need to reference to run this code?

    Dec 16, 2015 at 2:21

  • 6

    formData.append('file', $('#file')[0].files[0]); returns undefined and console.log(formData) has nothing except _proto_

    Aug 5, 2016 at 9:52

  • 6

    I got this to work…Pinch me, I’m on jQuery Ajax file upload heaven! var formData = new FormData(); formData.append('file', document.getElementById('file').files[0]); $.ajax({ url : $("form[name='uploadPhoto']").attr("action"), type : 'POST', data : formData, processData: false, // tell jQuery not to process the data contentType: false, // tell jQuery not to set contentType success : function(data) { console.log(data); alert(data); } });

    – TARKUS

    Jan 30, 2017 at 22:43

  • 2

    @RaymondWachaga That’s encoding type, not encryption type. 🙂

    Jun 28, 2018 at 6:29

  • 2

    I was really struggling with this… After hours of researching and so forth, I found this that really helped. Thanks mate! The first part of your solution worked like a charm for me. That’s exactly what I needed 🙂

    – Damoiskii

    Jul 23, 2021 at 1:30