48

I have designed a simple form which allows the user to upload files to the server. Initially the form contains one 'browse' button. If the user wants to upload multiple files, he needs to click on the "Add More Files" button which adds another 'browse' button in the form. When the form is submitted, the file upload process is handled in 'upload.php' file. It works perfectly fine for uploading multiple files. Now I need to submit the form by using jQuery's '.submit()' and send a ajax ['.ajax()'] request to the 'upload.php' file to handle the file upload.

Here is my HTML form :

<form enctype="multipart/form-data" action="upload.php" method="post">
    <input name="file[]" type="file" />
    <button class="add_more">Add More Files</button>
    <input type="button" id="upload" value="Upload File" />
</form>

Here is the JavaScript :

$(document).ready(function(){
    $('.add_more').click(function(e){
        e.preventDefault();
        $(this).before("<input name='file[]' type='file' />");
    });
});

Here is the code for processing file upload :

for($i=0; $i<count($_FILES['file']['name']); $i++){
$target_path = "uploads/";
$ext = explode('.', basename( $_FILES['file']['name'][$i]));
$target_path = $target_path . md5(uniqid()) . "." . $ext[count($ext)-1]; 

if(move_uploaded_file($_FILES['file']['tmp_name'][$i], $target_path)) {
    echo "The file has been uploaded successfully <br />";
} else{
    echo "There was an error uploading the file, please try again! <br />";
}

}

Any suggestions on how I should write my '.submit()' function will be really helpful.

Rivnat
  • 1,497
  • 1
  • 20
  • 34
  • I think you should use one of these process either you can submit or u can upload by ajax.. What you want its not clear – Manish Shukla Oct 10 '13 at 12:47
  • 1
    http://stackoverflow.com/questions/166221/how-can-i-upload-files-asynchronously-with-jquery Similar question with possible solutions. – Awemo Oct 10 '13 at 12:59
  • Either submit or upload, anything will work for me. But the file upload is the main priority. – Rivnat Oct 10 '13 at 13:15

4 Answers4

61

Finally I have found the solution by using the following code:

$('body').on('click', '#upload', function(e){
        e.preventDefault();
        var formData = new FormData($(this).parents('form')[0]);

        $.ajax({
            url: 'upload.php',
            type: 'POST',
            xhr: function() {
                var myXhr = $.ajaxSettings.xhr();
                return myXhr;
            },
            success: function (data) {
                alert("Data Uploaded: "+data);
            },
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
        return false;
});
Rivnat
  • 1,497
  • 1
  • 20
  • 34
  • Why don't you accept Kalai's answer as it pretty much covers everything you needed – Onimusha Oct 28 '13 at 11:57
  • 18
    Kalai's answer generates multiple errors. That is the reason why I did not accept. But I am glad and grateful to him as he tried to help. – Rivnat Oct 28 '13 at 12:05
  • 2
    Nice and simple solution, though in the code you posted above you missed a ; at the end.. – skechav Nov 17 '16 at 01:20
  • How can we get this browsed files(formData) in php? – V.P Jul 10 '17 at 10:22
  • @V.P You can access the submitted file related data in PHP by using the Superglobal variable $_FILES. – Rivnat Jul 10 '17 at 10:35
  • I have submitted the form via ajax. How can I access those data in php function. – V.P Jul 10 '17 at 10:40
  • http://i.prntscr.com/c0bJbIVwRJ2G0Ubun_JTZQ.png . Is this the code that needs to be used in php function.(refer screenshot). – V.P Jul 10 '17 at 10:47
  • @V.P As I mentioned in my earlier comment, you can access the files related data using $_FILES. But if you have submitted other form elements you can access them using $_POST. You can use the codes from the screenshot you have referred if you think it serves your purpose. – Rivnat Jul 11 '17 at 04:12
  • @Rivnat I tried like this: Mage::log('ghj'.count($_POST['file']['name']), null, '107171.log'); But it logs result as 0. Please help. – V.P Jul 11 '17 at 05:20
  • @Rivnat I tried like this too: Mage::log('ghj'.count($_FILES['file']['name']), null, '107171.log'); But it also logs result as 0. Please help. – V.P Jul 11 '17 at 05:44
  • @V.P Please try setting your input name as file like in your HTML from and see if it still counts 0? – Rivnat Jul 12 '17 at 03:45
  • @Rivnat This is my html form field: – V.P Jul 12 '17 at 04:45
  • @V.P I think it will be better if you post a question with detailed code and explain your queries there then several people can help you with your issues. It is a bit difficult to resolve issues in the comments section of a question. – Rivnat Jul 12 '17 at 05:14
  • @Rivnat Can you please refer this link: https://stackoverflow.com/questions/45008669/save-multiple-browsed-file-to-a-folder – V.P Jul 12 '17 at 05:18
53

HTML

<form enctype="multipart/form-data" action="upload.php" method="post">
    <input name="file[]" type="file" />
    <button class="add_more">Add More Files</button>
    <input type="button" value="Upload File" id="upload"/>
</form>

Javascript

 $(document).ready(function(){
    $('.add_more').click(function(e){
        e.preventDefault();
        $(this).before("<input name='file[]' type='file'/>");
    });
});

for ajax upload

$('#upload').click(function() {
    var filedata = document.getElementsByName("file"),
            formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    var i = 0, len = filedata.files.length, img, reader, file;

    for (; i < len; i++) {
        file = filedata.files[i];

        if (window.FileReader) {
            reader = new FileReader();
            reader.onloadend = function(e) {
                showUploadedItem(e.target.result, file.fileName);
            };
            reader.readAsDataURL(file);
        }
        if (formdata) {
            formdata.append("file", file);
        }
    }
    if (formdata) {
        $.ajax({
            url: "/path to upload/",
            type: "POST",
            data: formdata,
            processData: false,
            contentType: false,
            success: function(res) {

            },       
            error: function(res) {

             }       
             });
            }
        });

PHP

for($i=0; $i<count($_FILES['file']['name']); $i++){
    $target_path = "uploads/";
    $ext = explode('.', basename( $_FILES['file']['name'][$i]));
    $target_path = $target_path . md5(uniqid()) . "." . $ext[count($ext)-1]; 

    if(move_uploaded_file($_FILES['file']['tmp_name'][$i], $target_path)) {
        echo "The file has been uploaded successfully <br />";
    } else{
        echo "There was an error uploading the file, please try again! <br />";
    }
}

/** 
    Edit: $target_path variable need to be reinitialized and should 
    be inside for loop to avoid appending previous file name to new one. 
*/

Please use the script above script for ajax upload. It will work

mujaffars
  • 1,395
  • 2
  • 15
  • 35
Kalaiyarasan
  • 12,134
  • 8
  • 31
  • 49
  • 1
    It shows "TypeError: document.getElementByName is not a function" for var filedata = document.getElementByName("file") – Rivnat Oct 10 '13 at 13:13
  • Sorry its a typo. replace document.getElementByName("file") with document.getElementsByName("file") – Kalaiyarasan Oct 10 '13 at 13:19
  • 2
    Still it shows "TypeError: filedata.files is undefined" for " var i = 0, len = filedata.files.length, img, reader, file; " – Rivnat Oct 10 '13 at 13:23
  • Better add 'multiple' attribute to file tag like it will allow you to upload multiple files in a single file tag – Kalaiyarasan Oct 10 '13 at 13:34
  • 2
    @Kalai: its showing this error "showUploadedItem is not defined". What should I do to fix it? – RobertH Feb 28 '14 at 13:39
  • That function i have not defined here, i.e., only for previewing the images. So comment that line – Kalaiyarasan Feb 28 '14 at 14:17
  • 2
    Its still reloading my page – mujaffars Sep 16 '15 at 09:46
  • Is there a way to modify this to add a progress bar for each file? – M H Nov 28 '15 at 04:02
  • 3
    @kalai It shows an error "filedata.files is undefined" for var "filedata = document.getElementsByName("file");" – V.P Jul 11 '17 at 10:56
  • This code is obsolete now - I'm also getting errors - TypeError: undefined is not an object (evaluating 'filedata.files.length') – K-G Jun 20 '19 at 07:10
  • change frome `formdata.append("file", file)` to `formdata.append("file[]", file)` works for me – vikyd Oct 16 '19 at 11:33
4

Using this source code you can upload multiple file like google one by one through ajax. Also you can see the uploading progress

HTML

 <input type="file" id="multiupload" name="uploadFiledd[]" multiple >
 <button type="button" id="upcvr" class="btn btn-primary">Start Upload</button>
 <div id="uploadsts"></div>

Javascript

    <script>

    function uploadajax(ttl,cl){

    var fileList = $('#multiupload').prop("files");
    $('#prog'+cl).removeClass('loading-prep').addClass('upload-image');

    var form_data =  "";

    form_data = new FormData();
    form_data.append("upload_image", fileList[cl]);


    var request = $.ajax({
              url: "upload.php",
              cache: false,
              contentType: false,
              processData: false,
              async: true,
              data: form_data,
              type: 'POST', 
              xhr: function() {  
                  var xhr = $.ajaxSettings.xhr();
                  if(xhr.upload){ 
                  xhr.upload.addEventListener('progress', function(event){
                      var percent = 0;
                      if (event.lengthComputable) {
                          percent = Math.ceil(event.loaded / event.total * 100);
                      }
                      $('#prog'+cl).text(percent+'%') 
                   }, false);
                 }
                 return xhr;
              },
              success: function (res, status) {
                  if (status == 'success') {
                      percent = 0;
                      $('#prog' + cl).text('');
                      $('#prog' + cl).text('--Success: ');
                      if (cl < ttl) {
                          uploadajax(ttl, cl + 1);
                      } else {
                          alert('Done');
                      }
                  }
              },
              fail: function (res) {
                  alert('Failed');
              }    
          })
    }

    $('#upcvr').click(function(){
        var fileList = $('#multiupload').prop("files");
        $('#uploadsts').html('');
        var i;
        for ( i = 0; i < fileList.length; i++) {
            $('#uploadsts').append('<p class="upload-page">'+fileList[i].name+'<span class="loading-prep" id="prog'+i+'"></span></p>');
            if(i == fileList.length-1){
                uploadajax(fileList.length-1,0);
            }
         }
    });
    </script>

PHP

upload.php
    move_uploaded_file($_FILES["upload_image"]["tmp_name"],$_FILES["upload_image"]["name"]);
sumit dugar
  • 121
  • 1
  • 6
Milan Krushna
  • 317
  • 2
  • 5
3

My solution

  • Assuming that form id = "my_form_id"
  • It detects the form method and form action from HTML

jQuery code

$('#my_form_id').on('submit', function(e) {
    e.preventDefault();
    var formData = new FormData($(this)[0]);
    var msg_error = 'An error has occured. Please try again later.';
    var msg_timeout = 'The server is not responding';
    var message = '';
    var form = $('#my_form_id');
    $.ajax({
        data: formData,
        async: false,
        cache: false,
        processData: false,
        contentType: false,
        url: form.attr('action'),
        type: form.attr('method'),
        error: function(xhr, status, error) {
            if (status==="timeout") {
                alert(msg_timeout);
            } else {
                alert(msg_error);
            }
        },
        success: function(response) {
            alert(response);
        },
        timeout: 7000
    });
});
SandroMarques
  • 6,070
  • 1
  • 41
  • 46