Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - SSH2 SFTP Downloads With Progress

Tags:

php

sftp

libssh2

I feel this deserves a question as StackOverflow doesn't seem to have enough on the subject.

I want to SFTP, using PHP with a Progress Bar

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:

  • Perform downloads via SFTP (over SSH?)
  • Give the user a visible indication of download progress
  • Enable the pausing and continuing of downloads

Think FileZilla, but in-browser, built with PHP. I don't want to hack Apache or add any Apache mods.


Options for the actual download

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.

The download progress

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...

And what about the pausing / continuing?

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.

Finally

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.

like image 779
Jimbo Avatar asked Mar 27 '13 16:03

Jimbo


1 Answers

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).

like image 122
Goran Jurić Avatar answered Sep 29 '22 07:09

Goran Jurić