3

I'm looking to allow a user to download a file directly from an sftp server, but in the browser.

I've found methods to read the file and echo the string (connections using ssh2.sftp or phpseclib) but I need to download, rather than read.

Also, I've seen solutions that suggest downloading from the sftp server to the web server, then use readfile() from the web server to the user's local disk. But this means two file transfers, and if the file is large I imagine this would be slow.

Can you download directly from sftp to the user's disk?

Cheers for any responses!

coffeedoughnuts
  • 505
  • 1
  • 5
  • 12
  • PHP has [FTP functions](http://www.php.net/manual/en/ref.ftp.php) – DarkBee Apr 22 '13 at 11:15
  • 2
    ** Never mind, I just got what you mean. All you need to do is force a download using the `Content-Disposition: attachment; filename="yourfile.ext"` header, and echo the data as you are doing. – DaveRandom Apr 22 '13 at 11:24
  • Cheers @DaveRandom - this seems to have worked! – coffeedoughnuts Apr 22 '13 at 12:09
  • actually - @DaveRandom - scratch that - seems to crap out on largeish files... I guess all this does it string out the file to a temporary location and then offer you a save... find for text and pics but not movie files, which is what i'm working with. – coffeedoughnuts Apr 22 '13 at 16:25
  • @user1019085 It shouldn't make any difference really, although you may have a server with output buffering enabled by default which might appear to slow it down - you can try adding `while (@ob_end_clean());` to the top of your script and test again. Also you could take a look at [`stream_copy_to_stream()`](http://php.net/stream-copy-to-stream), which is a little more efficient than echoing in a loop - although you will need to use a stream pointer to `php://output` to use this, which is a little more complex. – DaveRandom Apr 22 '13 at 16:30

1 Answers1

5

You don't need any php in order to allow the user to download directly from the SFTP server, if you add a direct link to the file to your html (i.e. Download Text). Of course this won't work if you don't want to make the credentials for the ftp server public.

If you are looking to pull the file from the SFTP through your server, you, by deffinition, must download the file to the server before sending it back out to the users browser.

For this there are many, many solutions. The least overhead would probably come from using phpseclib as below

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

//adds the proper headers to tell browser to download rather than display
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary"); 
header("Content-disposition: attachment; filename=\"filename.remote\""); 

// outputs the contents of filename.remote to the screen
echo $sftp->get('filename.remote');
?>

Unfortunately, if the file is larger than is allowed in memory by your server/php configuration, then this well cause problems.

If you want to take it a step further, you might try

//adds the proper headers to tell browser to download rather than display
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary"); 
header("Content-disposition: attachment; filename=\"filename.remote\""); 

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "sftp://full_file_url.file"); #input
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_setopt($curl, CURLOPT_USERPWD, "$_FTP[username]:$_FTP[password]");
curl_exec($curl);
curl_close($curl);

More information on using cURL can be found in the PHP Manual Documentation. Using curl_exec() without setting the CURLOPT_RETURNTRANSFER option to true causes curl to send the output (the file) directly to the browser.

Reid Johnson
  • 1,394
  • 14
  • 20