Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload progress bar using session in PHP 5.4 with codeigniter

With reference to this tutorial. Tracking upload progress with php . I want to make it work in Codeigniter. I am not getting point to start to make it work in CI. I want to upload files and also track progress.

In my CI view

 <?php $arr = array("id"=>"myform");
       echo form_open_multipart("welcome/uploads",$arr); ?>
      <input type="hidden" value="myForm" name="<?php echo ini_get("session.upload_progress.name"); ?>">
      <table>
      <tr>
          <td>file</td>
         <td><input type="file" name="images[]" multiple></td>
     </tr>
     <tr>
         <td>name</td>
         <td><input type="text" name="naam"></td>
    </tr>
    <tr>
        <td></td>
        <td><input type="submit"></td>
    </tr>
</table>
<?php echo form_close(); ?>
<div id="bar_blank">

script

function toggleBarVisibility() {
  var e = document.getElementById("bar_blank");
  e.style.display = (e.style.display == "block") ? "none" : "block";
}

function createRequestObject() {
   var http;
   if (navigator.appName == "Microsoft Internet Explorer") {
       http = new ActiveXObject("Microsoft.XMLHTTP");
   }
   else {
      http = new XMLHttpRequest();
  }
     return http;
}

 function sendRequest() {
   var http = createRequestObject();
   http.open("GET", "<?php echo base_url().'index.php/welcome/progress' ?>");
   http.onreadystatechange = function () { handleResponse(http); };
   http.send(null);
 }

function handleResponse(http) {
   var response;
   if (http.readyState == 4) {
    response = http.responseText;
    document.getElementById("bar_color").style.width = response + "%";
    document.getElementById("status").innerHTML = response + "%";

    if (response < 100) {
        setTimeout("sendRequest()", 1000);
    }
    else {
        toggleBarVisibility();
        document.getElementById("status").innerHTML = "Done.";
      }
   }
}

 function startUpload() {
     toggleBarVisibility();
    setTimeout("sendRequest()", 1000);
 }

 (function () {
      document.getElementById("myForm").onsubmit = startUpload;  //error is here
})();

According to above tutorials, its in core php. When submitting form CI request to controller dashboard/addRoom and my page gets refresh anyhow. But in tutorials, Form redirects to PHP_SELF (same php file). I am not getting any idea on it. Please help me.

Controller

 function progress()
    {
        session_start();

        $key = ini_get("session.upload_progress.prefix") . "myForm";
        if (!empty($_SESSION[$key])) {
            $current = $_SESSION[$key]["bytes_processed"];
            $total = $_SESSION[$key]["content_length"];
            echo $current < $total ? ceil($current / $total * 100) : 100;
        }
        else {
            echo 100;
        }
    }
    public function uploads()
    {
        if(!empty($_FILES['images']['name'][0]))
       {
        //uploadinf file code
       }
    }
like image 473
user254153 Avatar asked Apr 19 '15 08:04

user254153


4 Answers

If you want to do it with only jQuery then i have used jQuery Form Submit Plugin, which will give you the progress and more. As you said in comments you don't need any plugin then follow these steps and implement like the tutorial suggesting.

Lets assume you have controller dashboard and method addRoom is displaying the your html form:

class Dashboard extends CI_Controller {


    function addRoom() {

        // Detect URI: http://example.com/dashboard/addRoom/upload_file
        $upload_req = $this->uri->segment("3");

        if( $upload_req == "upload_file" ) {
            // Do the file upload Actions
        }

        // Generate Form
        $this->load->view("Generate_view");
    }

}

View:

<?php 
    $ar = array("class"=>"form-horizontal");
    echo form_open_multipart('dashboard/addRoom/upload_file',$ar);
 ?>
 <input type="text" name="fileName">
 <input type="file" name="upload">
 <input type="submit" value="add">
 <?php echo form_close(); ?>

In this case your form is still on the same controller and method even you submit or not.

Update: According to updated answer, please use codeigniter default libraries for Session and File Uploads, In case of JS error, use console tab(Chrome) to debug error, or if you are using firefox then use firebug extension to debug Javascript.

like image 106
jogesh_pi Avatar answered Nov 09 '22 05:11

jogesh_pi


If you just want to show upload progress there are many plugins available to do so, I don't know why you specifically mentioned Session in you title.

Here is a very nice and simple plugin which will work with any PHP framework with ease.

Code Sample

<script>
/*jslint unparam: true */
/*global window, $ */
$(function () {
    'use strict';
    // Change this to the location of your server-side upload handler:
    var url = window.location.hostname === 'blueimp.github.io' ?
                '//jquery-file-upload.appspot.com/' : 'server/php/';
    $('#fileupload').fileupload({
        url: url,
        dataType: 'json',
        done: function (e, data) {
            $.each(data.result.files, function (index, file) {
                $('<p/>').text(file.name).appendTo('#files');
            });
        },
        progressall: function (e, data) {
            var progress = parseInt(data.loaded / data.total * 100, 10);
            $('#progress .progress-bar').css(
                'width',
                progress + '%'
            );
        }
    }).prop('disabled', !$.support.fileInput)
        .parent().addClass($.support.fileInput ? undefined : 'disabled');
});
</script>

enter image description here

like image 29
Murtaza Khursheed Hussain Avatar answered Nov 09 '22 03:11

Murtaza Khursheed Hussain


You're missing (I don't see it in your code) that the tutorial in your question declare and use an hidden iframe in the target attribute of the the upload form, this is a way to handle uploads preventing the form page to refresh (the action url will be loaded into the iframe).

google for hidden iframe upload (and eventually for formdata upload which nowadays should be a better way to handle uploads and show progress with few javascript)

here an old example which use the hidden iframe Ajax File Upload Response Handling

update

You should change the code in your view to $arr = array("id"=>"myForm")

Currently I see it is array("id"=>"myform") (all lowercase)

getElementById is case sensitive and you use .getElementById("myForm").onsubmit

When you use some javascript and something isn't working as expected the browser's javascript console is the first place to look, you should see an error like (chrome):

Uncaught TypeError: Cannot set property 'onsubmit' of null

This is because getElementById fail to find an element with id myForm and return null, in the html/DOM it is really named myform.

update

So, I got the thing working, instead of welcome controller I've created a new Upload controller (uppercase because I'm using CI 3 dev, should be easy to adapt it to old versions), below the working files.

The url will be http://your-host/optional-dir/index.php/upload.

application/controllers/Upload.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Upload extends CI_Controller {
    public function index() {
        $this->load->helper(array('form', 'url'));
        $this->load->view('upload');
    }
    function progress() {
        session_start();
        $key = ini_get("session.upload_progress.prefix") . "myForm";
        if (!empty($_SESSION[$key])) {
            $current = $_SESSION[$key]["bytes_processed"];
            $total = $_SESSION[$key]["content_length"];
            echo $current < $total ? ceil($current / $total * 100) : 100;
        }  else {
            echo 100;
        }
    }
    public function uploads() {
        if(!empty($_FILES['images']['name'][0]))  {
            //uploadinf file code
        }
    }
}

application/views/upload.php:

<!DOCTYPE html>
<html>
    <head>
        <title>upload</title>
        <style>
            #bar_blank {
                border: solid 1px #000;
                height: 20px;
                width: 300px;
            }

            #bar_color {
                background-color: #006666;
                height: 20px;
                width: 0px;
            }

            #bar_blank, #hidden_iframe {
                display: none;
            }
        </style>
    </head>
    <body>
        <?php $arr = array("id"=>"myForm", "target"=>"hidden_iframe");
        echo form_open_multipart("upload/uploads",$arr); ?>
        <input type="hidden" value="myForm" name="<?php echo ini_get("session.upload_progress.name"); ?>">
        <table>
            <tr>
                <td>file</td>
                <td><input type="file" name="images[]" multiple></td>
            </tr>
            <tr>
                <td>name</td>
                <td><input type="text" name="naam"></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit"></td>
            </tr>
        </table>
        <?php echo form_close(); ?>
        <iframe id="hidden_iframe" name="hidden_iframe" src="about:blank"></iframe>
        <div id="status"></div>
        <div id="bar_blank">
            <div id="bar_color"></div>
        </div>
        <?php include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'upload.js.php'); ?>
    </body>
</html>

./application/views/upload.js.php:

<script>
function toggleBarVisibility() {
    console.log('toggleBarVisibility');
    var e = document.getElementById("bar_blank");
    e.style.display = (e.style.display == "block") ? "none" : "block";
}

function createRequestObject() {
    console.log('createRequestObject');
    var http;
    if (navigator.appName == "Microsoft Internet Explorer") {
        http = new ActiveXObject("Microsoft.XMLHTTP");
    } else {
        http = new XMLHttpRequest();
    }
    return http;
}

function sendRequest() {
    console.log('sendRequest');
    var http = createRequestObject();
    http.open("GET", "<?php echo base_url().'index.php/upload/progress' ?>");
    http.onreadystatechange = function () { handleResponse(http); };
    http.send(null);
}

function handleResponse(http) {
    console.log('handleResponse');
    var response;
    if (http.readyState == 4) {
        response = http.responseText;
        document.getElementById("bar_color").style.width = response + "%";
        document.getElementById("status").innerHTML = response + "%";

        if (response < 100) {
            setTimeout("sendRequest()", 1000);
        } else {
            toggleBarVisibility();
            document.getElementById("status").innerHTML = "Done.";
        }
    }
}

function startUpload() {
    console.log('startUpload');
    toggleBarVisibility();
    setTimeout("sendRequest()", 1000);
}

(function () {
    console.log('init');
    document.getElementById("myForm").onsubmit = startUpload;  //error is here
})();

</script>

notice

I'm using a raw include_once for convenience, because php base_url is used inside the javascript, probably would be better have a small inline javascript in the view's html which declare a javascript variable with the base_url value then include the static javascript from an assets directory as usual.

like image 30
Alex Avatar answered Nov 09 '22 04:11

Alex


the tutorial i have seen actually you have to write AJAX in your view, and call the controller via ajax not via form submission with button. so than your page will not get refreshed. take a close look on the tutorial you have provided the link, and when you scroll down you will see javascript where it send HTTP requests via AJAX for example

 function createRequestObject() {
  var http;
  if (navigator.appName == "Microsoft Internet Explorer") {
     http = new ActiveXObject("Microsoft.XMLHTTP");
   }
   else {
    http = new XMLHttpRequest();
  }
   return http;
}

this is a 1 function where it create XMLHttpRequests to get response from file where you have to get response via XMLHttpRequest from your controller.

Regards

like image 1
imran qasim Avatar answered Nov 09 '22 03:11

imran qasim