SFTP file is not downloaded completelly with ssh2.sftp and fread - php

I am working on a log file download for a separate system that requires SFTP for viewing logs. I am able to view the available log files on the server and download them. My issue is that it seems that the download stops at 2K which, in most cases, is only the first 10 lines of the log file. The files should contain thousands of lines as they are daily logs of changes made to the system.
I have done this in two separate files, one loads all of the files onto a page where the user can select the available log files and click a link to view the contents in the browser:
$ftp_server = "IP of Server";
$ftp_user_name = "USERNAME";
$ftp_user_pass = "PASSWORD";
$connection = ssh2_connect($ftp_server, 22);
ssh2_auth_password($connection,$ftp_user_name, $ftp_user_pass);
$sftp = ssh2_sftp($connection);
$dh = opendir("ssh2.sftp://$sftp//EMSftp/audit_files/");
while (($file = readdir($dh)) !== false) {
if ($file != '.' && $file != '..'){
if (strpos($file,"2017-04")){
echo '/EMSftp/audit_files/'.$file.' | curl
| view<br>';
}
}
}
closedir($dh);
I have tried to download the files two different ways using sftp and ssh2:
$file = $_GET['file'];
$local_file = "/var/www/uploads/logs/$file";
if (!file_exists($local_file)){
$connection = ssh2_connect($ftp_server, 22);
ssh2_auth_password($connection,$ftp_user_name, $ftp_user_pass);
$sftp = ssh2_sftp($connection);
$stream = #fopen("ssh2.sftp://$sftp//EMSftp/audit_files/$file", 'r');
if (! $stream)
throw new Exception("Could not open file: $remote_file");
$contents = fread($stream, filesize("ssh2.sftp://$sftp//EMSftp/audit_files/$file"));
file_put_contents ($local_file, $contents);
#fclose($stream);
}
echo '<pre>';
echo file_get_contents($local_file);
echo '</pre>';
and also tried to accomplish this using curl. This only creates a blank file. Not sure what is missing here. Unable to add the file contents to the file.
$file = $_GET['file'];
$local_file = "/var/www/uploads/logs/$file";
fopen($local_file, 'w+');
chmod($local_file, 0777);
$remote = "sftp://$ftp_user_name:$ftp_user_pass#$ftp_server//EMSftp/audit_files/$file";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $remote);
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_setopt($curl, CURLOPT_USERPWD, "$ftp_user_name:$ftp_user_pass");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$somecontent = curl_exec($curl);
if (is_writable($local_file)) {
if (!$handle = fopen($local_file, 'a')) {
echo "Cannot open file ($local_file)";
exit;
}
if (fwrite($handle, $somecontent) === FALSE) {
echo "Cannot write to file ($local_file)";
exit;
}
echo "Success, wrote ($somecontent) to file ($local_file)";
fclose($handle);
} else {
echo "The file $local_file is not writable";
}
curl_close($curl);
Not sure where I am missing something. Wondering if there is a time out related to this procedure that I am overlooking. Any help?

This is wrong:
$contents = fread($stream, filesize("ssh2.sftp://$sftp//EMSftp/audit_files/$file"));
It does not guarantee you, that a whole file will be read.
As documented:
fread() reads up to length bytes
If the logs are of reasonable size, use simple file_get_contents:
$contents = file_get_contents("ssh2.sftp://$sftp//EMSftp/audit_files/$file");
If not, read the file in chunks in a loop:
$stream = #fopen("ssh2.sftp://$sftp//EMSftp/audit_files/$file", 'r');
while (!feof($stream))
{
$chunk = fread($stream, 8192);
// write/append chunk to a local file
}
#fclose($stream);

Related

PHP CLI - FTP Multiple Files

Complete newbie and still learning.
I have PHP 7.2 installed on windows 7 and using it as a CLI to move files around.
I can upload files to several FTP servers fine. I'd like to now to be able to upload all files within a folder.
I can do one at a time but it just doesn't seem like the most efficient way to do it.
Here is a sample snippet of my upload script for a single file upload:
<?php
$ostream = fopen("ssh2.sftp://$sftp" . $remoteFile_Official, 'w');
$ofile = file_get_contents($localFile_Official);
fwrite($ostream, $ofile);
fclose($ostream);
?>
Thanking you advance.
Try this .
<?php
$dir = "/images/";
// Open a directory, and read its contents
if (is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
$ostream = fopen("ssh2.sftp://$sftp" . $file, 'w');
$ofile = file_get_contents($localFile_Official);
fwrite($ostream, $ofile);
fclose($ostream);
}
closedir($dh);
}
}
?>
Here is the complete code
// set up basic ssl ftp connection
$conn_id = ssh2_connect($ftp_server, 22);
ssh2_auth_password($conn_id, $ftp_username, $ftp_userpass);
// Open SSL session
$sftp = ssh2_sftp($conn_id);
$Official = "/FTP/LPS Data/ATC/RHIL/20190119_RHIL/XML";
$dir = "Z:\adminshare\Rosehill\190119_Rosehill Gardens\XML\Race_4\\";
// Open a directory, and read its contents
if (is_dir($dir)){
if ($dh = opendir($dir)){
while (($file = readdir($dh)) !== false){
$stream = fopen("ssh2.sftp://$sftp" . $file, 'w');
$file = file_get_contents($remoteFile_Official);
fwrite($stream, $file);
fclose($stream);
}
closedir($dh);
}
}
Hope that helps a bit more

How Can php know if the image has been loaded fully?

I wrote a PHP script which simply gets URL for images and tries to download/save them on server.
My problem here is that sometimes the image is not fully loaded and the codes blow only save images partially. I did some research but couldn't figure out if I can add something to it, so it can check whether it is saving the full image or not.
Images sizes and other properties of images are random so I can't check it with those factors unless there is a way that I can get those info before loading them image.
Thank you all.
if ( $leng >= "5" ) {
define('UPLOAD_DIR', dirname(__FILE__) . '/files/');
$length = 512000;
$handle = fopen($url, 'rb');
$filename = UPLOAD_DIR . substr(strrchr($url, '/'), 1);
$write = fopen($filename, 'w');
while (!feof($handle))
{
$buffer = fread($handle, $length);
fwrite($write, $buffer);
}
fclose($handle);
fclose($write);
}else {Echo "failed";}
I think that using cURL is a better solution than using fopen for url. Check this out:
$file = fopen($filename, 'wb'); //Write it as a binary file - like image
$c = curl_init($url);
curl_setopt($c, CURLOPT_FILE, $file);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, true); //Allow cURL to follow redirects (but take note that this does not work with safemode enabled)
curl_exec($c);
$httpCode = curl_getinfo($c, CURLINFO_HTTP_CODE); //200 means OK, you may check it later, just for sure
curl_close($c);
fclose($file);
Partially based on Downloading a large file using curl

PHP - reading FTP file without downloading it/saving it locally

I would like to get FTP files content without saving it locally.
This is what I have so far:
$ftp_server = "my_server";
$ftp_conn = ftp_connect($ftp_server) or die("Could not connect to the server");
if (#ftp_login($ftp_conn, "username", "password")) {
$local_file = 'C:\Users\user\Desktop\testing.txt';
$fp = fopen($local_file, "w");
$d = ftp_nb_fget($ftp_conn, $fp, "commands.yml", FTP_BINARY);
while ($d == FTP_MOREDATA) {
$d = ftp_nb_continue($ftp_conn);
}
if ($d != FTP_FINISHED) {
echo "Error downloading $server_file";
exit(1);
}
ftp_close($ftp_conn);
fclose($fp);
$filename = 'C:\Users\user\Desktop\testing.txt';
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
echo $contents;
} else {
echo "Couldn't establish a connection.";
}
The code above saves the file and read the file content. Is it possible to read the file without saving it locally?
From the answer on the official PHP site from bob at notallhere dot com:
Don't want to use an intermediate file? Use 'php://output' as the
filename and then capture the output using output buffering.
ob_start();
$result = ftp_get($ftp, "php://output", $file, FTP_BINARY);
$data = ob_get_contents();
ob_end_clean();

PHP ftp upload times out(File is 12 byte)

I have a problem creating a local file, then uploading it to ftp server.
Here is my code:
$file = 'test';
$string = $phone.','.$y.','.$z;
$fp = fopen($file, 'w+');
fwrite($fp, $string);
fclose($fp);
$fp = fopen($file, 'r');
$conn_id = ftp_connect('domain');
ftp_login($conn_id, 'user', 'pass');
if (ftp_fput($conn_id, $file, $fp, FTP_BINARY)) {
} else {
}
ftp_close($conn_id);
fclose($fp);
unlink($file);
I dont get any error, I just exceed memory. I dont have any other problems with the ftp server, anywhere else but when I am uploading. As I said the file is only 12 bytes.

Uploading file through FTP using PHP

I'm curious how to upload file through FTP using PHP. Let's say I have upload form and user have uploaded a file. How to transfer the file (without moving from temp directory) to some FTP host using PHP?
Here you go:
$ftp = ftp_connect($host, $port, $timeout);
ftp_login($ftp, $user, $pass);
$ret = ftp_nb_put($ftp, $dest_file, $source_file, FTP_BINARY, FTP_AUTORESUME);
while (FTP_MOREDATA == $ret)
{
// display progress bar, or something
$ret = ftp_nb_continue($ftp);
}
// all done :-)
Error handling omitted for brevity.
Please note: you have to have ext-ftp installed and enabled.
Here is a code sample
$ftp_server="";
$ftp_user_name="";
$ftp_user_pass="";
$file = "";//tobe uploaded
$remote_file = "";
// set up basic connection
$conn_id = ftp_connect($ftp_server);
// login with username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
// upload a file
if (ftp_put($conn_id, $remote_file, $file, FTP_ASCII)) {
echo "successfully uploaded $file\n";
exit;
} else {
echo "There was a problem while uploading $file\n";
exit;
}
// close the connection
ftp_close($conn_id);
How about FTP upload via Curl? (Note: you can also use curl for SFTP, FTPS)
<?php
$ch = curl_init();
$localfile = '/path/to/file.zip';
$remotefile = 'filename.zip';
$fp = fopen($localfile, 'r');
curl_setopt($ch, CURLOPT_URL, 'ftp://ftp_login:password#ftp.domain.com/'.$remotefile);
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localfile));
curl_exec ($ch);
$error_no = curl_errno($ch);
curl_close ($ch);
if ($error_no == 0) {
$error = 'File uploaded succesfully.';
} else {
$error = 'File upload error.';
}
?>
Here's a function to do it for you.
function uploadFTP($server, $username, $password, $local_file, $remote_file){
// connect to server
$connection = ftp_connect($server);
// login
if (#ftp_login($connection, $username, $password)){
// successfully connected
}else{
return false;
}
ftp_put($connection, $remote_file, $local_file, FTP_BINARY);
ftp_close($connection);
return true;
}
Usage:
uploadFTP("127.0.0.1", "admin", "mydog123", "C:\\report.txt", "meeting/tuesday/report.txt");
For anyone want to show a the upload progress while doing file transfers, this is a great library php-ftp-client to start :
The code
$interval = 1;
$ftp->asyncDownload('illustrations/assets.zip', 'assets.zip', function ($stat) use ($interval) {
ob_end_clean();
ob_start();
echo sprintf(
"speed : %s KB/%ss | percentage : %s%% | transferred : %s KB | second now : %s <br>",
$stat['speed'],
$interval,
$stat['percentage'],
$stat['transferred'],
$stat['seconds']
);
ob_flush();
flush();
}, true, $interval);
Result in the browser :
FTP password must be in single quote otherwise it will not accept special characters
$ftp_server="";
$ftp_user_name="";
$ftp_user_pass=''; // this is the right way
$file = "";//tobe uploaded
$remote_file = "";

Categories