I feel this deserves a question as StackOverflow doesn't seem to have enough on the subject.
I love progress bars. However, this time I want to do something a little different. I want to do the following with PHP, and this one looks a lot harder than the last:
Think FileZilla, but in-browser, built with PHP. I don't want to hack Apache or add any Apache mods.
There are plenty of questions here, here, here and here for the basic SFTP download.
These document PHP's SSH2 extension (which I am using at the moment - you install this via pecl) and the alternative PHPSecLib, which I'm not using, but may look into later.
My interface allows swapping in/out easily - coding to the interface rather than the implementation etc...
That's great, but they just perform the actual download and that's it.
PHP has a really interesting callback called stream_notification_callback
, which you can read more about here.
This looks great, and was a promising step until someone looked into the source code of PHP and found that, unfortunately, SSH2 / SFTP doesn't allow integration with this.
Thanks to hek2mgl for putting in the effort to research this.
The idea with stream_notification_callback
was to pass a notification of the current download size every time data is retrieved; therefore giving the data required to calculate a percentage using the currently downloaded amount and the total file size. But that doesn't go with SSH2 and SFTP...
In my opinion, this would be the hardest to accomplish. Downloading data to a temporary file would be possible... Here's what I managed to dig up: http://ee.php.net/manual/en/function.fread.php#84115 - But integrating that sort of code with the progress bar seems crazy.
There's also cURL, however I didn't see the pausing / resuming of downloads as possible with this over SFTP. Correct me if I'm wrong.
So, how would I go about integration of the aforementioned requirements in-browser using PHP? Forget the client-side stuff, just getting the data to the browser is enough, so recommendations to perform this would be great.
Here is a sample I took from this site:
// Write from our remote stream to our local stream
$read = 0;
$fileSize = filesize("ssh2.sftp://$sftp/$fileName");
while ($read < $fileSize && ($buffer = fread($remoteStream, $fileSize - $read))) {
// Increase our bytes read
$read += strlen($buffer);
// Write to our local file
if (fwrite($localStream, $buffer) === FALSE) {
throw new Exception("Unable to write to local file: /localdir/$fileName");
}
}
Since you have the size of the file and you read from it with fread it is trivial to determine your progress.
Pausing can be done by checking a value from lets say APC that you set if user clicks on the Pause button (do this in an iframe so you do not stop the main script).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With