83

Does anyone know how to get a progress bar for an upload in php? I am trying writing code for a photo album uploader. I would like a progress bar to display while the photos are uploading.

I am fairly new to php so I dont know everything about it.

casperOne
  • 73,706
  • 19
  • 184
  • 253
Josh Curren
  • 10,171
  • 17
  • 62
  • 73
  • http://stackoverflow.com/questions/10477135/simple-cross-browser-jquery-php-file-upload-with-progress-bar/10477249#10477249 – Alfred Jun 15 '13 at 07:42

10 Answers10

70

This is by far (after hours of googling and trying scripts) the simplest to set up and nicest uploader I've found

https://github.com/FineUploader/fine-uploader

It doesn't require APC or any other external PHP libraries, I can get file progress feedback on a shared host, and it claims to support html5 drag and drop (personally untested) and multiple file uploads.

Ray Nicholus
  • 19,538
  • 14
  • 59
  • 82
Jesse
  • 10,370
  • 10
  • 62
  • 81
  • 11
    You'll want to use this instead I believe: https://github.com/valums/file-uploader - same author. – Michael Reed Apr 01 '11 at 03:23
  • 6
    And please see [Session Upload Progress](http://www.php.net/manual/en/session.upload-progress.php) which is what PHP offers to obtain progress for a file-upload out of the box. – hakre Oct 22 '11 at 16:56
  • 1
    The Session Upload Progress functionality mentioned by @hakre requires PHP 5.4, which is still in beta. However, similar functionality was introduced in PHP 5.2 in the [Alternative PHP Cache](http://us3.php.net/manual/en/ref.apc.php). – arlomedia Oct 28 '11 at 21:18
  • 7
    @jpeskin that's kind of unfair to the developer. just because you "offer to pay them" doesn't obligate them like some kind of prostitute to do work for you. if you can't figure out how to debug it, then i wouldn't go around pointing fingers at anybody other than yourself-- software you find on the internet is provided "as is" so don't go around bashing people who are doing nothing more than trying to help. – sucitivel Jun 02 '12 at 14:31
  • to follow up @MichaelReed's github posting, the project has actually moved, and is being actively maintained here: https://github.com/Valums-File-Uploader/file-uploader – sucitivel Jun 02 '12 at 18:31
  • 4
    @sucitivel To be more detailed: I offered to pay and he accepted, then we went through the trouble to document all bugs we were seeing, and then he stopped responding to any and all emails (simply polite ones, requesting a status update and whether he was still interested in the work). I don't consider anyone obligated to work for money. It was merely an observational data point for others who might want to know about the developer's availability and/or interest in freelance work. The project was forked, so I wasn't the only one sensing the dev was losing interest in maintaining. – jpeskin Jun 04 '12 at 22:03
  • 5
    http://blueimp.github.com/jQuery-File-Upload/ - this works really good. At least I like it as it is not lagging under Ubuntu =) – BeRocket Nov 13 '12 at 17:16
  • THe project linked to in the description is quite active. There was an alternate link in the comments to a much older fork that hasn't been updated in over a year. – Ray Nicholus Feb 05 '14 at 15:18
13

If you have APC installed, it has a callback hook for upload progress.

Rasmus Lerdorf (PHP's creator) has a sample of this using YUI (oh, and here's the PHP source).

See the documentation here.

Ariel
  • 25,995
  • 5
  • 59
  • 69
Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • Neither the same or the php source links work anymore.. do you have an alt link please? – supersan Oct 28 '16 at 08:51
  • @supersan This answer is very out of date. APC is dead, and the Session Upload API is a [separate thing](http://php.net/manual/en/session.upload-progress.php) now. It also doesn't work if the server is using FastCGI... which most do for security reasons these days. – Powerlord Oct 29 '16 at 00:11
13

I'm sorry to say that to the best of my knowledge a pure PHP upload progress bar, or even a PHP/Javascript upload progress bar is not possible because of how PHP works. Your best bet is to use some form of Flash uploader.

AFAIK This is because your script is not executed until all the superglobals are populated, which includes $_FILES. By the time your PHP script gets called, the file is fully uploaded.

EDIT: This is no longer true. It was in 2010.

Macha
  • 14,366
  • 14
  • 57
  • 69
  • 13
    Why the three downvotes? It's true and they're completely unjustified. I dare anyone to show me a progress bar that runs on native PHP, and doesn't need extra extensions / Apache modules / perl scripts / other stuff to work. – Pekka Jan 20 '10 at 16:43
  • 1
    Well, it's 2011 and it's now possible thanks to HTML5. See the first response here: http://stackoverflow.com/questions/76976/how-to-get-progress-from-xmlhttprequest – Zarel Jun 16 '11 at 01:52
  • 10
    Well, it's 2012, and file upload in HTML5 through XMLHttpRequest is still not available in all major browsers. – Damien B Apr 28 '12 at 16:14
  • 3
    @Pekka웃 It's not true. If you have APC installed (and you should) you can do it completely natively in PHP, and no javascript either. – Ariel Jan 18 '13 at 11:04
  • 2
    @Pekka웃 Not to mention uploading using session information in PHP >=5.4. – Wookie88 May 24 '13 at 19:48
8

One PHP-ish (5.2+) & no-Flash way that worked nicely for me:

First, see this post explaining how to get "uploadprogress" extension up and running.

Then, in the page containing the form that you are uploading file(s) from, create the following iframe:

<iframe id="progress_iframe" src="" style="display:none;" scrolling="no" frameborder="0"></iframe>

Next, add this code to your "Submit" button:

onclick="function set() { f=document.getElementById('progress_iframe'); f.style.display='block'; f.src='uploadprogress.php?id=<?=$upload_id?>';} setTimeout(set);"

Now you have a hidden iframe in your form that will come visible and show contents of uploadprogress.php when you click "Submit" to start uploading files. $upload_id must be the same that you are using as the value of hidden field "UPLOAD_IDENTIFIER" in your form.

The uploadprogress.php itself looks about like this (fix and adjust to your needs):

<html>
<head>
<META HTTP-EQUIV='REFRESH' CONTENT='1;URL=?id=<?=$_GET['id']?>'>
</head>
<body>
Upload progress:<br />
<?php
    if(!$_GET['id']) die;
    $info = uploadprogress_get_info($_GET['id']);
    $kbytes_total = round($info['bytes_total'] / 1024);
    $kbytes_uploaded = round($info['bytes_uploaded'] / 1024);
    echo $kbytes_uploaded.'/'.$kbytes_total.' KB';
?>
</body>
</html>

Note that is self-refreshes every second. You can surely add some nice visual progress bar here (like 2 nested <div>s with different colors) if you like. The iframe with upload progress naturally only works while the upload is in progress, and ends its visible life once the form is submitted and browser reloads to the next page.

glennsl
  • 28,186
  • 12
  • 57
  • 75
IvarsK
  • 81
  • 1
  • 1
3

Implementation of the upload progress bar is easy and doesn't require any additional PHP extension, JavaScript or Flash. But you need PHP 5.4 and newer.

You have to enable collecting of the upload progress information by setting the directive session.upload_progress.enabled to On in php.ini.

Then add a hidden input to the HTML upload form just before any other file inputs. HTML attribute name of that hidden input should be the same as the value of the directive session.upload_progress.name from php.ini (eventually preceded by session.upload_progress.prefix). The value attribute is up to you, it will be used as part of the session key.

HTML form could looks like this:

<form action="upload.php" method="POST" enctype="multipart/form-data">
   <input type="hidden" name="<?php echo ini_get('session.upload_progress.prefix').ini_get('session.upload_progress.name'); ?>" value="myupload" />
   <input type="file" name="file1" />
   <input type="submit" />
</form>

When you send this form, PHP should create a new key in the $_SESSION superglobal structure which will be populated with the upload status information. The key is concatenated name and value of the hidden input.

In PHP you can take a look at populated upload information:

var_dump($_SESSION[
    ini_get('session.upload_progress.prefix')
   .ini_get('session.upload_progress.name')
   .'_myupload'
]);

The output will look similarly to the following:

$_SESSION["upload_progress_myupload"] = array(
  "start_time" => 1234567890,   // The request time
  "content_length" => 57343257, // POST content length
  "bytes_processed" => 54321,   // Amount of bytes received and processed
  "done" => false,              // true when the POST handler has finished, successfully or not
  "files" => array(
    0 => array(
      "field_name" => "file1",    // Name of the <input /> field
      // The following 3 elements equals those in $_FILES
      "name" => "filename.ext",
      "tmp_name" => "/tmp/phpxxxxxx",
      "error" => 0,
      "done" => false,            // True when the POST handler has finished handling this file
      "start_time" => 1234567890, // When this file has started to be processed
      "bytes_processed" => 54321, // Number of bytes received and processed for this file
    )
  )
);

There is all the information needed to create a progress bar — you have the information if the upload is still in progress, the information how many bytes is going to be transferred in total and how many bytes has been transferred already.

To present the upload progress to the user, write an another PHP script than the uploading one, which will only look at the upload information in the session and return it in the JSON format, for example. This script can be called periodically, for example every second, using AJAX and information presented to the user.

You are even able to cancel the upload by setting the $_SESSION[$key]['cancel_upload'] to true.

For detailed information, additional settings and user's comments see PHP manual.

glennsl
  • 28,186
  • 12
  • 57
  • 75
David Ferenczy Rogožan
  • 23,966
  • 9
  • 79
  • 68
2

Gears and HTML5 have a progress event in the HttpRequest object for submitting a file upload via AJAX.

http://developer.mozilla.org/en/Using_files_from_web_applications

Your other options as already answered by others are:

  1. Flash based uploader.
  2. Java based uploader.
  3. A second comet-style request to the web server or a script to report the size of data received. Some webservers like Lighttpd provide modules to do this in-process to save the overhead of calling an external script or process.

Technically there is a forth option, similar to YouTube upload, with Gears or HTML5 you can use blobs to split a file into small chunks and individually upload each chunk. On completion of each chunk you can update the progress status.

Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
Steve-o
  • 12,678
  • 2
  • 41
  • 60
2

Another uploader full JS : http://developers.sirika.com/mfu/

  • Its free ( BSD licence )
  • Internationalizable
  • cross browser compliant
  • you have the choice to install APC or not ( underterminate progress bar VS determinate progress bar )
  • Customizable look as it uses dojo template mechanism. You can add your class / Ids in the te templates according to your css

have fun

2

HTML5 introduced a file upload api that allows you to monitor the progress of file uploads but for older browsers there's plupload a framework that specifically made to monitor file uploads and give information about them. plus it has plenty of callbacks so it can work across all browsers

Darren
  • 68,902
  • 24
  • 138
  • 144
the master
  • 21
  • 2
1

You would need to use Javascript to create a progress bar. A simple Google search led me to this article: WebAppers Simple Javascript Progress Bar with CSS.

Dojo File Upload Progress Bar Widget is another option using the Dojo Javascript framework.

EDIT: Assuming your uploading a large number of images (such as a photo album), and POSTing them to your PHP script, you could use javascript to read the results back from the post and update the progress bar based on the number of images uploaded / total number of images. This has the side effect of only updating after each post has completed. Check out here for some info on how to post with JS.

Joey Robert
  • 7,336
  • 7
  • 34
  • 31
  • 6
    -1 The Javascript progress bar is nice but has nothing to do with file uploads as far as I can see. And the Dojo upload progress bar is not providing any interface to PHP.Correct me if I'm wrong of course. – Pekka Jan 20 '10 at 16:43
1

A php/ajax progress bar can be done. (Checkout the Html_Ajax library in pear). However this requires installing a custom module into php.

Other methods require using an iframe, through which php looks to see how much of the file has been uploaded. However this hidden iframe, may be blocked by some browsers addons because hidden iframes are often used to send malicious data to a users computer.

Your best bet is to use some form of flash progress bar if you do not have control over your server.

Ali Lown
  • 2,323
  • 1
  • 18
  • 22
  • Some add-ons might block iframes, but browsers? Can you give an example? – ya23 Jan 20 '10 at 16:55
  • Googling the terms "ajax php file upload" returns 4 of the top 5 results all using iframes (not sure if the 5th does (page won't load)). Take a look at the examples on each of the sites. – Ali Lown Jan 20 '10 at 18:49
  • Indeed, they use iframes, but don't mention it can be blocked in any case. Or have I missed that? – ya23 Jan 21 '10 at 09:53
  • Sorry, mis-read what you were trying to ask, no, I cannot give any examples of browsers that directly block iframes, I was thinking of the addons that people use with them such as noscript which blocks iframes. Updated text in post for future reference. – Ali Lown Jan 21 '10 at 18:18