Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding unobtrusive progress bar to old-school file uploads

You all know the new generation of fancy, mostly Flash-based file uploaders like SWFUpload that can show a progress bar while uploading - a great improvement especially for shaky and low-bandwidth connections.

However, these uploaders all bring their own logic of how to handle uploads on the client side. I am looking for an unobtrusive way to "fancify" existing, classical file uploads, i.e. introducing a progress bar to normal file upload forms.

Due to the architecture of uploading files, this is most likely not possible without some tweaking on the client side.

I am looking for a solution that keeps the tweaking to an absolute minimum, e.g. a component that adds itself to the onsubmit event of a normal form, performs the file upload, displays a nice progress bar, puts the resulting temporary (server side) file path into the form, and submits it. On the server side, I just have to modify my script to use the file path provided by the flash uploader, instead of $_FILES and consorts, and think about security for a moment.

This is not exactly what all the Flash-based uploaders do: They can use data from a form, but they do not provide possibilities to submit the form as is, what is what I'm looking for. I am looking for a (probably) Flash based upload function taken a step further.

like image 873
Pekka Avatar asked Oct 30 '09 14:10

Pekka


3 Answers

If you use PHP 5.2 and up this file upload progress tutorial by IBM can help you.

This multiple file upload tutorial uses jQuery + AJAX Upload... It uses $_FILES on the server side and will transform a special <div> on the client side to make a <form>. I guess you could tweak it to fit your needs.

If tweaking the last one is too tricky, Uber-Uploader on SourceForge is another option.

There are dozens of open source project covering this topic. Unfortunately this is not something trivial to implement seamlessly (at least in the way you want - otherwise we would have saw this in the good old Netscape days already).

On the bright side, HTML5 will ease this as you can see in this demo and this one.

I hope this helps and good luck with you integration.

like image 92
AlexV Avatar answered Oct 19 '22 16:10

AlexV


We implemented this very simple by installing the PECL extension pecl-uploadprogress and added a simple AJAX callback to the forms:

Generate an upload key:

$upload_id = genUploadKey();
function genUploadKey ($length = 11) {
  $charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  for ($i=0; $i < $length; $i++)
    $key .= $charset[(mt_rand(0,(strlen($charset)-1)))];
  return $key;
}

Create an AJAX callback handler (eg. uploadprogress.php):

extract($_REQUEST);

// servlet that handles uploadprogress requests:
if ($upload_id) {
  $data = uploadprogress_get_info($upload_id);
  if (!$data)
    $data['error'] = 'upload id not found';
  else {
    $avg_kb = $data['speed_average'] / 1024;
    if ($avg_kb<100)
      $avg_kb = round($avg_kb,1);
    else if ($avg_kb<10)
      $avg_kb = round($avg_kb,2);
    else $avg_kb = round($avg_kb);

    // two custom server calculations added to return data object:
    $data['kb_average'] = $avg_kb;
    $data['kb_uploaded'] = round($data['bytes_uploaded'] /1024);
  }

  echo json_encode($data);
  exit;
}

// display on completion of upload:
if ($UPLOAD_IDENTIFIER) {
...

Download jQuery and the jQuery.uploadprogress libraries (which also includes the above snippet) and integrate with your form:

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.uploadprogress.0.3.js"></script>
<script type="text/javascript">
jQuery(function () {
    // apply uploadProgress plugin to form element
    // with debug mode and array of data fields to publish to readout:
    jQuery('#upload_form').uploadProgress({
        progressURL:'uploadprogress.php',
        displayFields : ['kb_uploaded','kb_average','est_sec'],
        start: function() {
            $('.upload-progress').show();
        },
    success: function() {
            $('.upload-progress').hide();
            jQuery(this).get(0).reset();
        }
    });
});
</script>

Add this to your upload form:

<input name="UPLOAD_IDENTIFIER" type="hidden" value="$upload_id" />

That should do the trick. This is extracted from our code base and may not work out-of-the-box. But it should tell you the idea.

like image 3
hurikhan77 Avatar answered Oct 19 '22 14:10

hurikhan77


jquploader uses the info inside the form, such as the action attribute value as upload script. But i haven't updated it in a while and it lacks all the belts and whistles scripts like uploadify have (which is an excellent script btw). See if it could be a base for you to tweak.

like image 3
pixeline Avatar answered Oct 19 '22 15:10

pixeline