855

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.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
Willy
  • 9,681
  • 5
  • 26
  • 25

26 Answers26

640

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.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Adeel
  • 19,075
  • 4
  • 46
  • 60
  • 44
    Here is a list of the specific browsers that are not supported: http://caniuse.com/#search=FormData Also I have not tested this but here is a polyfill for FormData https://gist.github.com/3120320 – Ryan White Oct 03 '12 at 00:34
  • 168
    Specifically, IE < 10 doesn't, for those too lazy to read the link. – Kevin Nov 01 '12 at 05:28
  • 2 thoughts: 1st - man this is what makes web development so hilariously wild west. 2nd : @ Vicary - it addresses "the jquery" portion of the question by simply stating it as an unreality as of the time/date posted - to those ends 100% accurate and helpful. ADEEL - +1 great answer if only because backwards compatibility is tantamount. – Brandt Solovij Jan 10 '13 at 23:34
  • 26
    @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. – Drew Calder Mar 06 '14 at 08:49
  • 36
    @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 :) – Nicolas Connault Jun 18 '14 at 04:10
  • @RyanWhite That isn't actually a FormData polyfill, but rather a polyfill for using FormData within HTML5 Web Workers (which isn't natively supported). This won't work if FormData isn't supported outside of Web Workers. – hofnarwillie Jun 22 '14 at 22:26
  • 1
    FormData is undefined in latest Chrome (38.0.2107.3-dev) – Steel Brain Aug 03 '14 at 21:54
  • 4
    [This link](http://blog.teamtreehouse.com/uploading-files-ajax) 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 '15 at 20:54
  • @DrewCalder IE is dead. – Said Torres Dec 05 '22 at 19:18
  • just not useful. – Tejas Tank Aug 11 '23 at 10:36
379

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;
}
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
JohannesAndersson
  • 4,550
  • 2
  • 17
  • 30
  • 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. – JohannesAndersson Jun 14 '12 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 '12 at 09: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()`? – tandrewnichols May 21 '13 at 11:30
  • @tandrewnichols That's in the AJAX `success` event. This proof-of-concept code is fine. Just use what's in the DOM `click` event, write whatever you want in the `success` AJAX event, remove the use of global variables, etc. It needs some cleaning up, but it definitely works. Thanks, @Ziinloader – stackular Apr 10 '14 at 16:25
  • 4
    What if the data also contains few fields along with file to upload? – raju Apr 29 '14 at 18:33
  • It is not supported in IE 8 and IE9. The file object will have only name and it does not have size and type. – user428747 Apr 16 '15 at 16:50
  • 2
    @user428747 That's known, but it's not the problem of this code, it's a technical limitation from IEs side (like always TBH). http://caniuse.com/#feat=xhr2 – Dennis98 Feb 07 '16 at 01:21
  • i want to check if uploading is finish but this code not work `if(percent == 100) { progress_bar_id.fadeOut(); }` please give some suggestion – navotera May 29 '17 at 00:41
  • @navotera I would strongly recommend you to put ` var progress_bar_id = $("#progress-wrp"); progress_bar_id.fadeOut();` in your ajax success callback. It will automatically be called when the image is successfully uploaded! Tried it my self just a minute ago and it works like a charm! – JohannesAndersson May 29 '17 at 09:46
  • 1
    thank it work. but i use this `$(progress_bar_id).fadeOut(2000);` – navotera May 29 '17 at 23:37
  • 5
    @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. – Regular Jo Oct 10 '17 at 21:39
  • 2
    *$(this)[0]* is *this* – StefansArya Jan 10 '18 at 16:16
  • In my case I added a `.show()` on the progress bar wrapper right before the ajax call, and a `complete` handler with a corresponding `.hide()`. Depending on your UI, this may reduce visual clutter when the upload isn't being interacted with. – jinglesthula Aug 23 '18 at 15:55
256

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
            ));
}
Community
  • 1
  • 1
pedrozopayares
  • 2,856
  • 1
  • 13
  • 14
  • 2
    What jquery library do i need to reference to run this code? – Rayden Black Dec 16 '15 at 02:21
  • The answer was written in 2014. The version of JQuery was 1.10. I have not tried with more recent versions. – pedrozopayares Apr 09 '16 at 19:51
  • 6
    `formData.append('file', $('#file')[0].files[0]);` returns `undefined` and `console.log(formData)` has nothing except `_proto_` – Yakob Ubaidi Aug 05 '16 at 09:52
  • 1
    Not supported by IE 9, in case some is stuck in the same hell as I – CountMurphy Jan 10 '17 at 15:40
  • 7
    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 '17 at 22:43
  • The trick is setting the encryption type in the ajax call like so: enctype : 'multipart/form-data', – Wachaga Mwaura Nov 21 '17 at 05:55
  • 2
    @RaymondWachaga That's encoding type, not encryption type. :) – Ted Bigham Jun 28 '18 at 06: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 '21 at 01:30
135

Simple Upload Form

<script>

   //form Submit
   $("form").submit(function(evt){   

      evt.preventDefault();
      var formData = new FormData($(this)[0]);

      $.ajax({
          url: 'fileUpload',
          type: 'POST',
          data: formData,
          async: false,
          cache: false,
          contentType: false,
          enctype: 'multipart/form-data',
          processData: false,
          success: function (response) {
         
             alert(response);
          }
       });

       return false;

    });

</script>
<!--Upload Form-->
<form>
  <table>
    <tr>
      <td colspan="2">File Upload</td>
    </tr>
    <tr>
      <th>Select File </th>
      <td><input id="csv" name="csv" type="file" /></td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="submit" value="submit"/> 
      </td>
    </tr>
  </table>
</form>
dewd
  • 4,380
  • 3
  • 29
  • 43
vickisys
  • 2,008
  • 2
  • 20
  • 27
  • sir what are the js that were used on this example is there a specific jquery plugin for this one..i have a question i was pointed here can you please check my question.. I want to upload multiple file or images in that project here is the link http://stackoverflow.com/questions/28644200/input-type-file-ajax-request?noredirect=1#comment45628551_28644200 – Brownman Revival Feb 24 '15 at 02:44
  • 27
    *$(this)[0]* is *this* – machineaddict May 20 '16 at 09:07
  • 2
    What is the parameter on the server for posted file? Can you please post server part. – FrenkyB Oct 27 '17 at 09:02
  • @FrenkyB and others - the files on the server (in PHP) are not stored in the $_POST variable - they are stored in the $_FILES variable. In this case, you would access it with $_FILES["csv"] because "csv" is the name attribute of the input tag. – dev_masta Apr 29 '18 at 22:09
  • perfectly right. – Tejas Tank Aug 11 '23 at 10:37
73

I'm pretty late for this but I was looking for an ajax based image uploading solution and the answer I was looking for was kinda scattered throughout this post. The solution I settled on involved the FormData object. I assembled a basic form of the code I put together. You can see it demonstrates how to add a custom field to the form with fd.append() as well as how to handle response data when the ajax request is done.

Upload html:

<!DOCTYPE html>
<html>
<head>
    <title>Image Upload Form</title>
    <script src="//code.jquery.com/jquery-1.9.1.js"></script>
    <script type="text/javascript">
        function submitForm() {
            console.log("submit event");
            var fd = new FormData(document.getElementById("fileinfo"));
            fd.append("label", "WEBUPLOAD");
            $.ajax({
              url: "upload.php",
              type: "POST",
              data: fd,
              processData: false,  // tell jQuery not to process the data
              contentType: false   // tell jQuery not to set contentType
            }).done(function( data ) {
                console.log("PHP Output:");
                console.log( data );
            });
            return false;
        }
    </script>
</head>

<body>
    <form method="post" id="fileinfo" name="fileinfo" onsubmit="return submitForm();">
        <label>Select a file:</label><br>
        <input type="file" name="file" required />
        <input type="submit" value="Upload" />
    </form>
    <div id="output"></div>
</body>
</html>

In case you are working with php here's a way to handle the upload that includes making use of both of the custom fields demonstrated in the above html.

Upload.php

<?php
if ($_POST["label"]) {
    $label = $_POST["label"];
}
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 200000)
&& in_array($extension, $allowedExts)) {
    if ($_FILES["file"]["error"] > 0) {
        echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
    } else {
        $filename = $label.$_FILES["file"]["name"];
        echo "Upload: " . $_FILES["file"]["name"] . "<br>";
        echo "Type: " . $_FILES["file"]["type"] . "<br>";
        echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";

        if (file_exists("uploads/" . $filename)) {
            echo $filename . " already exists. ";
        } else {
            move_uploaded_file($_FILES["file"]["tmp_name"],
            "uploads/" . $filename);
            echo "Stored in: " . "uploads/" . $filename;
        }
    }
} else {
    echo "Invalid file";
}
?>
Musa
  • 96,336
  • 17
  • 118
  • 137
lee8oi
  • 1,169
  • 8
  • 12
  • i am getting `Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https,` why is this so sir i copy paste your code as it is – Brownman Revival Feb 21 '15 at 11:07
  • 2
    @HogRider - if you Google your error message, this is the first result: http://stackoverflow.com/questions/10752055/cross-origin-requests-are-only-supported-for-http-error-when-loading-a-local Are you accessing your web pages locally through `file://`, rather than using a web server? As an aside, it is not best practice to simply copy-and-paste code blindly without first understanding it. I would recommend you go through the code line-by-line to gain an understanding of what is happening before putting the code to use. – colincameron Mar 18 '15 at 13:12
  • @colincameron thank you for clarify a few things i did go through the it line by line and i dont really understand much so i asked the question so that someone might clarify my doubts. I am using local by way xampp to be exact. Can i ask a question that maybe you can clarify? – Brownman Revival Mar 19 '15 at 01:45
  • @Brownman Revival : I know that its too late for the reply.. You got a cross origin error because you opened the html file as file than running it from the server. – Adarsh Mohan Nov 22 '15 at 12:20
  • How do I apply form action based on selection in this code? – Rayden Black Dec 16 '15 at 02:14
  • u must open the html page from the server – Adarsh Mohan Dec 16 '15 at 03:07
35

An AJAX upload is indeed possible with XMLHttpRequest(). No iframes necessary. Upload progress can be shown.

For details see: Answer https://stackoverflow.com/a/4943774/873282 to question jQuery Upload Progress and AJAX file upload.

Giulio Caccin
  • 2,962
  • 6
  • 36
  • 57
koppor
  • 19,079
  • 15
  • 119
  • 161
  • 24
    Unfortunately IE < 10 don't support this. – Sasha Chedygov Dec 10 '12 at 21:02
  • 1
    When you merely want to refer to another page as an answer, you can vote to close as a dupkucate or leave a comment under the question. This post is Not An Answer. A post of this kind looks like an attempt to farm rep. – mickmackusa Nov 24 '19 at 07:29
29

Here's how I got this working:

HTML

<input type="file" id="file">
<button id='process-file-button'>Process</button>

JS

$('#process-file-button').on('click', function (e) {
    let files = new FormData(), // you can consider this as 'data bag'
        url = 'yourUrl';

    files.append('fileName', $('#file')[0].files[0]); // append selected file to the bag named 'file'

    $.ajax({
        type: 'post',
        url: url,
        processData: false,
        contentType: false,
        data: files,
        success: function (response) {
            console.log(response);
        },
        error: function (err) {
            console.log(err);
        }
    });
});

PHP

if (isset($_FILES) && !empty($_FILES)) {
    $file = $_FILES['fileName'];
    $name = $file['name'];
    $path = $file['tmp_name'];


    // process your file

}
М.Б.
  • 1,308
  • 17
  • 20
  • 3
    What helped the most for me about this was the `$('#file')[0].files[0]` which is some sort of strange JS workaround without requiring a proper `
    `
    – ffgpga08 Jan 18 '19 at 17:00
  • 2
    This is the complete solution, the PHP bit helps too. – cdsaenz Jul 26 '19 at 16:22
29

Using pure js it is easier

async function saveFile(inp) 
{
    let formData = new FormData();           
    formData.append("file", inp.files[0]);
    await fetch('/upload/somedata', {method: "POST", body: formData});    
    alert('success');
}
<input type="file" onchange="saveFile(this)" >
  • In server side you can read original file name (and other info) which is automatically included to request.
  • You do NOT need to set header "Content-Type" to "multipart/form-data" browser will set it automatically
  • This solutions should work on all major browsers.

Here is more developed snippet with error handling, timeout and additional json sending

async function saveFile(inp) 
{
    let user = { name:'john', age:34 };
    let formData = new FormData();
    let photo = inp.files[0];      
         
    formData.append("photo", photo);
    formData.append("user", JSON.stringify(user));  
    
    const ctrl = new AbortController() // timeout
    setTimeout(() => ctrl.abort(), 50000);

    try {
       let r = await fetch('/upload/image', 
         {method: "POST", body: formData, signal: ctrl.signal}); 
       console.log('HTTP response code:',r.status); 
       alert('success');
    } catch(e) {
       console.log('Huston we have problem...:', e);
    }
    
}
<input type="file" onchange="saveFile(this)" >
<br><br>
Before selecting the file Open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
19

In case you want to do it like that:

$.upload( form.action, new FormData( myForm))
.progress( function( progressEvent, upload) {
    if( progressEvent.lengthComputable) {
        var percent = Math.round( progressEvent.loaded * 100 / progressEvent.total) + '%';
        if( upload) {
            console.log( percent + ' uploaded');
        } else {
            console.log( percent + ' downloaded');
        }
    }
})
.done( function() {
    console.log( 'Finished upload');                    
});

than

https://github.com/lgersman/jquery.orangevolt-ampere/blob/master/src/jquery.upload.js

might be your solution.

lgersman
  • 2,178
  • 2
  • 19
  • 21
  • Where is the upload method in $ object, the above link is not existing – coolesting Dec 20 '12 at 03:41
  • https://github.com/lgersman/jquery.orangevolt-ampere/blob/master/src/jquery.upload.js – lgersman Jan 04 '13 at 08:57
  • 2
    Thanks for posting your answer! Please be sure to read the [FAQ on Self-Promotion](http://stackoverflow.com/faq#promotion) carefully. Also note that it is *required* that you post a disclaimer every time you link to your own site/product. – Andrew Barber Apr 08 '13 at 15:28
19

Use FormData. It works really well :-) ...

var jform = new FormData();
jform.append('user',$('#user').val());
jform.append('image',$('#image').get(0).files[0]); // Here's the important bit

$.ajax({
    url: '/your-form-processing-page-url-here',
    type: 'POST',
    data: jform,
    dataType: 'json',
    mimeType: 'multipart/form-data', // this too
    contentType: false,
    cache: false,
    processData: false,
    success: function(data, status, jqXHR){
        alert('Hooray! All is well.');
        console.log(data);
        console.log(status);
        console.log(jqXHR);

    },
    error: function(jqXHR,status,error){
        // Hopefully we should never reach here
        console.log(jqXHR);
        console.log(status);
        console.log(error);
    }
});
rrk
  • 15,677
  • 4
  • 29
  • 45
delboy1978uk
  • 12,118
  • 2
  • 21
  • 39
18
$("#submit_car").click(function() {
  var formData = new FormData($('#car_cost_form')[0]);
  $.ajax({
     url: 'car_costs.php',
     data: formData,
     contentType: false,
     processData: false,
     cache: false,
     type: 'POST',
     success: function(data) {
       // ...
     },
  });
});

edit: Note contentype and process data You can simply use this to upload files via Ajax...... submit input cannot be outside form element :)

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
Gvice
  • 393
  • 2
  • 10
17

2019 update:

html

<form class="fr" method='POST' enctype="multipart/form-data"> {% csrf_token %}
<textarea name='text'>
<input name='example_image'>
<button type="submit">
</form>

js

$(document).on('submit', '.fr', function(){

    $.ajax({ 
        type: 'post', 
        url: url, <--- you insert proper URL path to call your views.py function here.
        enctype: 'multipart/form-data',
        processData: false,
        contentType: false,
        data: new FormData(this) ,
        success: function(data) {
             console.log(data);
        }
        });
        return false;

    });

views.py

form = ThisForm(request.POST, request.FILES)

if form.is_valid():
    text = form.cleaned_data.get("text")
    example_image = request.FILES['example_image']
Jay
  • 1,289
  • 3
  • 11
  • 22
  • 3
    How dow this improve any of the answers already given? Also this answer mentions a views.py file which is Django and has nothing to do with the question. – dirkgroten Mar 13 '19 at 16:23
16
  • Use a hidden iframe and set your form's target to that iframe's name. This way, when the form is submitted, only the iframe will be refreshed.
  • Have an event handler registered for the iframe's load event to parse the response.
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Manki
  • 3,779
  • 4
  • 25
  • 18
10

Using FormData is the way to go as indicated by many answers. here is a bit of code that works great for this purpose. I also agree with the comment of nesting ajax blocks to complete complex circumstances. By including e.PreventDefault(); in my experience makes the code more cross browser compatible.

    $('#UploadB1').click(function(e){        
    e.preventDefault();

    if (!fileupload.valid()) {
        return false;            
    }

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

    $("#UpdateMessage5").html("Uploading file ....");
    $("#UpdateMessage5").css("background","url(../include/images/loaderIcon.gif) no-repeat right");

    myformData.append('mode', 'fileUpload');
    myformData.append('myid', $('#myid').val());
    myformData.append('type', $('#fileType').val());
    //formData.append('myfile', file, file.name); 

    $.ajax({
        url: 'include/fetch.php',
        method: 'post',
        processData: false,
        contentType: false,
        cache: false,
        data: myformData,
        enctype: 'multipart/form-data',
        success: function(response){
            $("#UpdateMessage5").html(response); //.delay(2000).hide(1); 
            $("#UpdateMessage5").css("background","");

            console.log("file successfully submitted");
        },error: function(){
            console.log("not okay");
        }
    });
});
Mike Volmar
  • 1,927
  • 1
  • 22
  • 31
9

I have implemented a multiple file select with instant preview and upload after removing unwanted files from preview via ajax.

Detailed documentation can be found here: http://anasthecoder.blogspot.ae/2014/12/multi-file-select-preview-without.html

Demo: http://jsfiddle.net/anas/6v8Kz/7/embedded/result/

jsFiddle: http://jsfiddle.net/anas/6v8Kz/7/

Javascript:

    $(document).ready(function(){
    $('form').submit(function(ev){
        $('.overlay').show();
        $(window).scrollTop(0);
        return upload_images_selected(ev, ev.target);
    })
})
function add_new_file_uploader(addBtn) {
    var currentRow = $(addBtn).parent().parent();
    var newRow = $(currentRow).clone();
    $(newRow).find('.previewImage, .imagePreviewTable').hide();
    $(newRow).find('.removeButton').show();
    $(newRow).find('table.imagePreviewTable').find('tr').remove();
    $(newRow).find('input.multipleImageFileInput').val('');
    $(addBtn).parent().parent().parent().append(newRow);
}

function remove_file_uploader(removeBtn) {
    $(removeBtn).parent().parent().remove();
}

function show_image_preview(file_selector) {
    //files selected using current file selector
    var files = file_selector.files;
    //Container of image previews
    var imageContainer = $(file_selector).next('table.imagePreviewTable');
    //Number of images selected
    var number_of_images = files.length;
    //Build image preview row
    var imagePreviewRow = $('<tr class="imagePreviewRow_0"><td valign=top style="width: 510px;"></td>' +
        '<td valign=top><input type="button" value="X" title="Remove Image" class="removeImageButton" imageIndex="0" onclick="remove_selected_image(this)" /></td>' +
        '</tr> ');
    //Add image preview row
    $(imageContainer).html(imagePreviewRow);
    if (number_of_images > 1) {
        for (var i =1; i<number_of_images; i++) {
            /**
             *Generate class name of the respective image container appending index of selected images, 
             *sothat we can match images selected and the one which is previewed
             */
            var newImagePreviewRow = $(imagePreviewRow).clone().removeClass('imagePreviewRow_0').addClass('imagePreviewRow_'+i);
            $(newImagePreviewRow).find('input[type="button"]').attr('imageIndex', i);
            $(imageContainer).append(newImagePreviewRow);
        }
    }
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        /**
         * Allow only images
         */
        var imageType = /image.*/;
        if (!file.type.match(imageType)) {
          continue;
        }

        /**
         * Create an image dom object dynamically
         */
        var img = document.createElement("img");

        /**
         * Get preview area of the image
         */
        var preview = $(imageContainer).find('tr.imagePreviewRow_'+i).find('td:first');

        /**
         * Append preview of selected image to the corresponding container
         */
        preview.append(img); 

        /**
         * Set style of appended preview(Can be done via css also)
         */
        preview.find('img').addClass('previewImage').css({'max-width': '500px', 'max-height': '500px'});

        /**
         * Initialize file reader
         */
        var reader = new FileReader();
        /**
         * Onload event of file reader assign target image to the preview
         */
        reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
        /**
         * Initiate read
         */
        reader.readAsDataURL(file);
    }
    /**
     * Show preview
     */
    $(imageContainer).show();
}

function remove_selected_image(close_button)
{
    /**
     * Remove this image from preview
     */
    var imageIndex = $(close_button).attr('imageindex');
    $(close_button).parents('.imagePreviewRow_' + imageIndex).remove();
}

function upload_images_selected(event, formObj)
{
    event.preventDefault();
    //Get number of images
    var imageCount = $('.previewImage').length;
    //Get all multi select inputs
    var fileInputs = document.querySelectorAll('.multipleImageFileInput');
    //Url where the image is to be uploaded
    var url= "/upload-directory/";
    //Get number of inputs
    var number_of_inputs = $(fileInputs).length; 
    var inputCount = 0;

    //Iterate through each file selector input
    $(fileInputs).each(function(index, input){

        fileList = input.files;
        // Create a new FormData object.
        var formData = new FormData();
        //Extra parameters can be added to the form data object
        formData.append('bulk_upload', '1');
        formData.append('username', $('input[name="username"]').val());
        //Iterate throug each images selected by each file selector and find if the image is present in the preview
        for (var i = 0; i < fileList.length; i++) {
            if ($(input).next('.imagePreviewTable').find('.imagePreviewRow_'+i).length != 0) {
                var file = fileList[i];
                // Check the file type.
                if (!file.type.match('image.*')) {
                    continue;
                }
                // Add the file to the request.
                formData.append('image_uploader_multiple[' +(inputCount++)+ ']', file, file.name);
            }
        }
        // Set up the request.
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url, true);
        xhr.onload = function () {
            if (xhr.status === 200) {
                var jsonResponse = JSON.parse(xhr.responseText);
                if (jsonResponse.status == 1) {
                    $(jsonResponse.file_info).each(function(){
                        //Iterate through response and find data corresponding to each file uploaded
                        var uploaded_file_name = this.original;
                        var saved_file_name = this.target;
                        var file_name_input = '<input type="hidden" class="image_name" name="image_names[]" value="' +saved_file_name+ '" />';
                        file_info_container.append(file_name_input);

                        imageCount--;
                    })
                    //Decrement count of inputs to find all images selected by all multi select are uploaded
                    number_of_inputs--;
                    if(number_of_inputs == 0) {
                        //All images selected by each file selector is uploaded
                        //Do necessary acteion post upload
                        $('.overlay').hide();
                    }
                } else {
                    if (typeof jsonResponse.error_field_name != 'undefined') {
                        //Do appropriate error action
                    } else {
                        alert(jsonResponse.message);
                    }
                    $('.overlay').hide();
                    event.preventDefault();
                    return false;
                }
            } else {
                /*alert('Something went wrong!');*/
                $('.overlay').hide();
                event.preventDefault();
            }
        };
        xhr.send(formData);
    })

    return false;
}
Ima
  • 1,111
  • 12
  • 22
  • @Bhargav: Please see the blog post for explanations: http://goo.gl/umgFFy. If you still have any query, get back to me Thanks – Ima Aug 13 '15 at 06:26
8

Yes you can, just use javascript to get the file, making sure you read the file as a data URL. Parse out the stuff before base64 to actually get the base 64 encoded data and then if you are using php or really any back end language you can decode the base 64 data and save into a file like shown below

Javascript:
var reader = new FileReader();
reader.onloadend = function ()
{
  dataToBeSent = reader.result.split("base64,")[1];
  $.post(url, {data:dataToBeSent});
}
reader.readAsDataURL(this.files[0]);


PHP:
    file_put_contents('my.pdf', base64_decode($_POST["data"]));

Of course you will probably want to do some validation like checking which file type you are dealing with and stuff like that but this is the idea.

Piacenti
  • 1,188
  • 10
  • 9
  • file_put_contents($fname, file_get_contents($_POST['data'])); file_get_contents deals with the decoding and data:// header – Nande May 21 '16 at 03:49
8

To get all your form inputs, including the type="file" you need to use FormData object. you will be able to see the formData content in the debugger -> network ->Headers after you will submit the form.

var url = "YOUR_URL";

var form = $('#YOUR_FORM_ID')[0];
var formData = new FormData(form);


$.ajax(url, {
    method: 'post',
    processData: false,
    contentType: false,
    data: formData
}).done(function(data){
    if (data.success){ 
        alert("Files uploaded");
    } else {
        alert("Error while uploading the files");
    }
}).fail(function(data){
    console.log(data);
    alert("Error while uploading the files");
});
David
  • 633
  • 8
  • 6
8
<html>
    <head>
        <title>Ajax file upload</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        <script>
            $(document).ready(function (e) {
            $("#uploadimage").on('submit', (function(e) {
            e.preventDefault();
                    $.ajax({
                    url: "upload.php", // Url to which the request is send
                            type: "POST", // Type of request to be send, called as method
                            data: new FormData(this), // Data sent to server, a set of key/value pairs (i.e. form fields and values)
                            contentType: false, // The content type used when sending data to the server.
                            cache: false, // To unable request pages to be cached
                            processData:false, // To send DOMDocument or non processed data file it is set to false
                            success: function(data)   // A function to be called if request succeeds
                            {
                            alert(data);
                            }
                    });
            }));
        </script>
    </head>
    <body>
        <div class="main">
            <h1>Ajax Image Upload</h1><br/>
            <hr>
            <form id="uploadimage" action="" method="post" enctype="multipart/form-data">
                <div id="image_preview"><img id="previewing" src="noimage.png" /></div>
                <hr id="line">
                <div id="selectImage">
                    <label>Select Your Image</label><br/>
                    <input type="file" name="file" id="file" required />
                    <input type="submit" value="Upload" class="submit" />
                </div>
            </form>
        </div>
    </body>
</html>
Nicomedes E.
  • 1,326
  • 5
  • 18
  • 27
Nikit Barochiya
  • 971
  • 11
  • 14
7

to upload a file which is submitted by user as a part of form using jquery please follow the below code :

var formData = new FormData();
formData.append("userfile", fileInputElement.files[0]);

Then send the form data object to server.

We can also append a File or Blob directly to the FormData object.

data.append("myfile", myBlob, "filename.txt");
VISHNU
  • 948
  • 8
  • 15
6

You can use method ajaxSubmit as follow :) when you select a file that need upload to server, form be submit to server :)

$(document).ready(function () {
    var options = {
    target: '#output',   // target element(s) to be updated with server response
    timeout: 30000,
    error: function (jqXHR, textStatus) {
            $('#output').html('have any error');
            return false;
        }
    },
    success: afterSuccess,  // post-submit callback
    resetForm: true
            // reset the form after successful submit
};

$('#idOfInputFile').on('change', function () {
    $('#idOfForm').ajaxSubmit(options);
    // always return false to prevent standard browser submit and page navigation
    return false;
});
});
Quy Le
  • 2,354
  • 25
  • 18
  • 2
    I believe you are talking about jquery [form](https://github.com/malsup/form) plugin. It is really the best option here, apart from the lack of details in your answer. – fotanus Jul 04 '14 at 17:56
  • @fotanus you're right! that script must use jquery form plugin to submit use method ajaxSubmit that define in jquery form plugin – Quy Le Jul 13 '14 at 06:04
5

If you want to upload file using AJAX here is code which you can use for file uploading.

$(document).ready(function() {
    var options = { 
                beforeSubmit:  showRequest,
        success:       showResponse,
        dataType: 'json' 
        }; 
    $('body').delegate('#image','change', function(){
        $('#upload').ajaxForm(options).submit();        
    }); 
});     
function showRequest(formData, jqForm, options) { 
    $("#validation-errors").hide().empty();
    $("#output").css('display','none');
    return true; 
} 
function showResponse(response, statusText, xhr, $form)  { 
    if(response.success == false)
    {
        var arr = response.errors;
        $.each(arr, function(index, value)
        {
            if (value.length != 0)
            {
                $("#validation-errors").append('<div class="alert alert-error"><strong>'+ value +'</strong><div>');
            }
        });
        $("#validation-errors").show();
    } else {
         $("#output").html("<img src='"+response.file+"' />");
         $("#output").css('display','block');
    }
}

Here is the HTML for Upload the file

<form class="form-horizontal" id="upload" enctype="multipart/form-data" method="post" action="upload/image'" autocomplete="off">
    <input type="file" name="image" id="image" /> 
</form>
Nikunj K.
  • 8,779
  • 4
  • 43
  • 53
4
var dataform = new FormData($("#myform")[0]);
//console.log(dataform);
$.ajax({
    url: 'url',
    type: 'POST',
    data: dataform,
    async: false,
    success: function(res) {
        response data;
    },
    cache: false,
    contentType: false,
    processData: false
});
Mohammad
  • 21,175
  • 15
  • 55
  • 84
Jayesh Paunikar
  • 148
  • 1
  • 7
4
<input class="form-control cu-b-border" type="file" id="formFile">
<img id="myImg" src="#">

In js

<script>
    var formData = new FormData();
    formData.append('file', $('#formFile')[0].files[0]);
    $.ajax({
        type: "POST",
        url: '/GetData/UploadImage',
        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);
            $('#myImg').attr('src', data);
        },
        error: function (xhr, ajaxOptions, thrownError) {
        }
    })
</script>

In controller

public ActionResult UploadImage(HttpPostedFileBase file)
        {
            string filePath = "";
            if (file != null)
            {
                string path = "/uploads/Temp/";
                if (!Directory.Exists(Server.MapPath("~" + path)))
                {
                    Directory.CreateDirectory(Server.MapPath("~" + path));
                }
                filePath = FileUpload.SaveUploadedFile(file, path);
            }
            
            return Json(filePath, JsonRequestBehavior.AllowGet);
        }
Abhishek Kanrar
  • 418
  • 4
  • 6
3

Here was an idea I was thinking of:

Have an iframe on page and have a referencer.

Have a form in which you move the input type file element to.

Form:  A processing page AND a target of the FRAME.

The result will post to the iframe, and then you can just send the fetched data up a level to the image tag you want with something like:

data:image/png;base64,asdfasdfasdfasdfa

and the page loads.

I believe it works for me, and depending you might be able to do something like:

.aftersubmit(function(){
    stopPropagation(); // or some other code which would prevent a refresh.
});
no ai please
  • 732
  • 3
  • 11
  • 24
Fallenreaper
  • 10,222
  • 12
  • 66
  • 129
  • I don't see how this improves any other answer given before. Also it's *Propagation* not propigation! ;) – JDuarteDJ Aug 14 '18 at 14:32
2

This is my code that it works

var formData = new FormData();
var files = $('input[type=file]');
for (var i = 0; i < files.length; i++) {
if (files[i].value == "" || files[i].value == null) {
 return false;
}
else {
 formData.append(files[i].name, files[i].files[0]);
}
}
var formSerializeArray = $("#Form").serializeArray();
for (var i = 0; i < formSerializeArray.length; i++) {
  formData.append(formSerializeArray[i].name, formSerializeArray[i].value)
}
$.ajax({
 type: 'POST',
 data: formData,
 contentType: false,
 processData: false,
 cache: false,
 url: '/Controller/Action',
 success: function (response) {
 if (response.Success == true) {
    return true;
 }
 else {
    return false;
 }
 },
 error: function () {
   return false;
 },
 failure: function () {
   return false;
 }
 });
keivan kashani
  • 1,263
  • 14
  • 15
1

$("#form-id").submit(function (e) {
   e.preventDefault();
});

$("#form-id").submit(function (e) {

     var formObj = $(this);
     var formURL = formObj.attr("action");
     var formData = new FormData(this);
          $.ajax({
             url: formURL,
             type: 'POST',
             data: formData,
             processData: false,
             contentType: false,
             async: true,
             cache: false,
             enctype: "multipart/form-data",
             dataType: "json",
             success: function (data) {
                 if (data.success) {
                        alert(data.success)
                 } 
                                
                 if  (data.error) {
                        alert(data.error)
                 } 
             }
         });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<form class="form-horizontal" id="form-id" action="masterFileController" enctype="multipart/form-data">
    <button class="btn-success btn" type="submit" id="btn-save" >Submit</button>
</form>

servlet responce as "out.print("your responce");"

biberman
  • 5,606
  • 4
  • 11
  • 35