php FTP Wrapper writes empty files (0 Byte), FTP Extension doesn't - php

On a server with PHP 5.2.17 running, using any function which makes use of the built in ftp wrapper to upload a file, creates an empty file on the server:
file_put_contents() returns with the accurate number of bytes
copy() also returns with true
Both create the file, but it's empty.
When trying with ftp_put() from the FTP extension, both in binary and ascii mode, it works well.
On my workstation with PHP 5.3.10 it somehow works also with the wrapper.
In code:
$source = '/tmp/testfile';
$target = 'ftp://user:pass#example.com/testfile';
copy($source, $target);
gives no error or warning, but leaves an empty file on the server.
$source = '/tmp/testfile';
$target = 'testfile';
$ftp = ftp_connect('example.com');
ftp_login($ftp, 'user', 'pass');
ftp_put($ftp, $target, $source, FTP_ASCII);
ftp_close($ftp);
works in every respect.
thanks for any suggestion!

Have you tried SSH2 libs? Some sample implementation below:
public function uploadSFTP($host_name, $port, $user, $publicSshKeyPath, $privateSshKeyPath, $remoteFile, $localFile, $fileOperation = 'w')
{
$ssh_conn = ssh2_connect($host_name, $port);
if (ssh2_auth_pubkey_file($ssh_conn, $user, $publicSshKeyPath, $privateSshKeyPath))
{
$sftp_conn = ssh2_sftp($ssh_conn);
$inputfileStream = #fopen('ssh2.sftp://' . $sftp_conn . $remoteFile, $fileOperation);
try
{
if (!$inputfileStream)
throw new Exception('Could open remote file for writing: ' . $remoteFile);
$localFileContents = #file_get_contents($localFile);
if ($localFileContents === FALSE)
throw new Exception('Could not open local file for reading :' . $localFile);
if (#fwrite($inputfileStream, $localFileContents) === FALSE)
throw new Exception('Could not SFTP file');
}
catch (Exception $e)
{
// Do something...
}
fclose($sftpInfileStream);
}
}

Related

Listing files on remote host failed

I have a code:
scandir("ssh2.sftp://" . intval($sftpHandle) . $remoteDir);
Why the same code works for one server but doesn't for another?
There is a files on both servers. I can manage them via Filezilla without problems.
The first one just returns array('.') even if there is a lot of files, another one returns array('file1', 'file2', 'file3', etc)
Even if I cannot list a files using scandir(), command ssh2_scp_recv($sshHandle, $remoteDir/file1, $localDir/file1) works fine.
Also ssh2_exec($sshHandle, "ls $remoteDir") works fine to me.
Please note that I'm using $ftpHandle for scandir() but $sshHandle for ssh2_* functions.
Using $sshHandle for scandir() cause "Segmentation fault" error.
I know that I can workaround this by parsing ssh2_exec($sshHandle, "ls $remoteDir") output, but would prefer do it right way if possible.
My PHP version is 7.0.31
This should work probably
$connection = ssh2_connect($url);
// login
if (!ssh2_auth_password($connection, $username, $password)) throw new Exception('Unable to connect server.');
// Create SFTP resource
if (!$sftp = ssh2_sftp($connection)) throw new Exception('Unable to create connection.');
$localDir = '/path/to/local/dir';
$remoteDir = '/path/to/remote/dir';
// download all the files or list all
$files = scandir('ssh2.sftp://' . $sftp . $remoteDir);
if (!empty($files)) {
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
// here you can print files using $file
// or download file by uncommenting below line
//ssh2_scp_recv($connection, "$remoteDir/$file", "$localDir/$file");
}
}
}

How to Copy one folder local file to SFTP server using PHP

This is my code to send single file from local to SFTP server. Single file successfully send.
I want to send one folder from local to SFTP server , but i dont know how to send one folder. i need help
<?php
$src = 'xxxxxxx';
$filename = 'test.txt';
$dest = 'xxxxxxxx'.$filename;
// set up sftp ssh-sftp connection
$connection = ssh2_connect('xxxxxx', 22);
ssh2_auth_password($connection, 'username', 'password');
// Create SFTP session
$sftp = ssh2_sftp($connection);
$sftpStream = #fopen('ssh2.sftp://'.$sftp.$dest, 'w');
try {
if (!$sftpStream) {
throw new Exception("Could not open remote file: $dest");
}
$data_to_send = #file_get_contents($src);
if ($data_to_send === false) {
throw new Exception("Could not open local file: $src.");
}
if (#fwrite($sftpStream, $data_to_send) === false) {
throw new Exception("Could not send data from file: $src.");
} else {
//Upload was successful, post-upload actions go here...
}
fclose($sftpStream);
} catch (Exception $e) {
error_log('Exception: ' . $e->getMessage());
fclose($sftpStream);
}
?>
ssh2_scp_send in php looks like just support sending file.
maybe these ways work:
1.compress folder, send the compressed file
2.use ssh2 to mkdir, then send each file iteratively
3.try with system() function to excute cmd line order "scp -r folder_path user#host:target_path"

Download a file to server from url , which is generated dynamically

I need to Download a zip file to my server from url , which is generated dynamically which means there will be no extension in url. zip file will be generated by the url. We need to save that zip file in the server.
I tried this.
function DownloadFile($reportDownloadUrl, $downloadPath) {
$reader = fopen(urldecode($reportDownloadUrl), 'rb') or die("url cannot open");
if (!file_exists($downloadPath)) {
die('File does not exist');
}
$writer = fopen($downloadPath, 'wb') or die("cannot open file");
if (!$reader) {
throw new Exception("Failed to open URL " . $reportDownloadUrl . ".");
}
if (!$writer) {
fclose($reader);
throw new Exception("Failed to create ZIP file " . $downloadPath . ".");
}
$bufferSize = 10 * 1024;
while (!feof($reader)) {
if (false === ($buffer = fread($reader, $bufferSize))) {
fclose($reader);
fclose($writer);
throw new Exception("Read operation from URL failed.");
}
if (fwrite($writer, $buffer) === false) {
fclose($reader);
fclose($writer);
$exception = new Exception("Write operation to ZIP file failed.");
}
}
fclose($reader);
fflush($writer);
fclose($writer);
}
By using this i can download the file which has extension .zip file, but i cannot download file which doesn't have extensions. I've been trying for ages to figure this out, there must be a way, any suggestions are greatly appreciated.
Thank you in advance.
There might be a couple reasons why you can't download a URL with no extension with your code. Your code is designed to read from a direct link, but sometimes there might be a redirect prior to that, or the file might not be accessible directly unless you send certain cookies, a user agent, a referrer, etc.
For that reason I recommend that you look into the cURL library. It provides a set of functions that allow you to easily perform all the aforementioned tasks. Here's a snippet that mimics your DownloadFile function, with the exception that it follows redirects :
function DownloadFile($reportDownloadUrl, $downloadPath) {
{
$ch = curl_init($reportDownloadUrl);
$fh = fopen($downloadPath, 'ab');
if($fh === false)
throw new Exception('Failed to open ' . $downloadPath);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fh); // file handle to write to
$result = curl_exec($ch);
if($result === false) // it's important to check the contents of curl_error if the request fails
throw new Exception('Unable to perform the request : ' . curl_error($ch));
}
cURL contains a lot of cool options like resuming a file download, uploading data, using proxies, etc. You can read all about it in the manual : http://php.net/curl-setopt
A few more things about your code :
The if(!$reader) and if(!$writer) checks are redundant because the script will die if the fopen() calls fail
You didn't throw $exception

ftp_fget() returns Transfer Complete error

I'm trying to download images from a remote FTP server and upload them to our own rackspace account. This goes fine for about 3000 images but then it crashes and gives me the following error:
exception with message 'ftp_fget(): Transfer complete.'
We've tried changing the code to use ftp_get(), to not use a temp file to store it in, but it always resulted in the same error. It always fails on the same files, if I were to delete a couple of files that were already downloaded and run the scripts again it has no problem downloading them... it just fails again once it hits those specific images on the FTP server. I've tried downloading those images manually from the server and it worked, it seems nothing is wrong with them.
This is basically the code that does it:
$this->handle = ftp_connect($ftpurl);
$loggedIn = ftp_login($this->handle, $ftpusername, $ftppassword);
if ($loggedIn === false) {
throw new Exception('Can\'t login to FTP server');
}
if ($this->handle === false) {
throw new Exception('Could not connect to the given url');
}
ftp_pasv($this->handle, true);
$fileList = ftp_nlist($this->handle, '.');
if (count($fileList) === 0) {
throw new Exception('No files found on FTP-server');
}
foreach($fileList as $filename) {
try {
$container->getObject($filename);
// Image already exists, rackspace has no convenient hasImage() function
} catch (Exception $ex) {
$temp = tmpfile();
ftp_fget($this->handle, $temp, $filename, FTP_BINARY);
//upload $tmp to rackspace
}
}
Any ideas what could be the issue here?

Uploading a file using WebDav protocol from Unix

I need to transfer a file from my Unix machine to a Windows machine. Problem is i can transfer a file already created on my machine via ftp from unix to any machine. also i can open webdav connection create new file and save it there.
What i am unable to do is to write my code to upload my file fro my local location using webdav.
i tried using pear client but due to lack of documentation, i am still not able to achieve the task .
Here is my attempt:
include("/usr/share/pear/HTTP/WebDAV/Client.php");
global $filename, $logger;
try {
/* $client = new HTTP_WebDAV_Client();
$user="username";
$pass = "pwd";
$dir = "webdavs://".$user.":".$pass."#hostname/";
var_dump($client->stream_open($dir."test4.txt","w",null,$path));
$client->stream_write("HELLO WORLD! , I am great ");
$client->stream_close();
$client->dir_opendir($dir,array());
var_dump($client->dirfiles);
$req =new HTTP_Request($dir);
$req->setBasicAuth($user, $pass);
$req->setMethod(HTTP_REQUEST_METHOD_POST);
$result = $req->addFile('file_upload_field', $filename);
if (PEAR::isError($result)) {
echo $result->getMessage();
} else {
$response = $req->sendRequest();
if (PEAR::isError($response)) {
echo $response->getMessage();
} else {
echo $req->getResponseBody();
}
}*/
$ftp_server = "hostname-ftp";
//$ftp_server = "hostname-webdav";
$connection = ftp_connect($ftp_server);
ftp_login($connection, 'user', 'pwd);
ftp_put($connection, $filename, $filename, FTP_BINARY);
unlink($filename);
} catch(Exception $e){
$message = "There was a problem while uploading" . $filename;
$logger->error($message);
}
It was a togh call, but i figured it out. I am adding my code snippet so it may be helpful for someone. Instead of uploading the file, i converted that file into data stream and then copied that data stream to my call that writes stream on webdav server.
try {
$filecsv = file_get_contents($filename);
$client = new HTTP_WebDAV_Client_Stream();
$user="user";
$pass = "pass";
$dir = "webdavs://".$user.":".$pass."#hostname/";
$client->stream_open($dir."db_user_exports.csv","w",null,$path);
$client->stream_write($filecsv);
$client->stream_close();
unlink($filename);
} catch(Exception $e){
$message = "There was a problem while uploading" . $filename;
$logger->error($message);
}

Categories