I have been trying for a few hours now to no avail. I have successfully output my CSV as a download in the browser using:
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=".$csv_filename."");
However I want that output to now go to an FTP server instead, I have got the connection and temp file part sorted but cannot seem to edit the file to output my results.
// create empty variable to be filled with export data
$csv_export = '';
for($i = 0; $i < $field; $i++) {
$csv_export.= mysql_field_name($query,$i).',';
}
// newline (seems to work both on Linux & Windows servers)
$csv_export.= '
';
// loop through database query and fill export variable
while($row = mysql_fetch_array($query)) {
// create line with field values
for($i = 0; $i < $field; $i++) {
$csv_export.= '"'.$row[mysql_field_name($query,$i)].'",';
}
$csv_export.= '
';
}
Above is the part that gets the query data and puts it into the CSV, I have tried incorporating both fputs and fputcsv in the loops to write the rows to the file.
//Upload the temporary file to server
ftp_fput($ftpstream, '/httpdocs/.../abandoned.csv', $temp, FTP_ASCII);
$fp = fopen('var/www/vhosts/.../abandoned.csv', 'w');
fputs($fp, '$csv_export');
fclose($fp);
echo($csv_export);
So, echoing the output works absolutely fine - all I want is that echo'd data written into a CSV file and uploaded to the FTP.
The error I've been given is:
Array ( [type] => 2 [message] => fclose() expects parameter 1 to be resource,
boolean given
So the fp is causing the problem... is it at the open stage or at the writing of csv_export?
Thanks in advance.
Try this
//Write the contents to the temp file
fputs($temp, $csv_export);
//upload the temp file
ftp_fput($ftpstream, '/httpdocs/.../abandoned.csv', $temp, FTP_ASCII);
//close the temp file
fclose($temp);
Your current code is creating an empty file, uploading it, and then creating a separate file. Even if you get it working on a local server, it is an unnecessary step.
Try this, not tested:
$filename = 'abandoned.csv';
$content = $csv_export;
$host = 'yourhost';
$user = 'youruser';
$password = 'yourpass';
//open connection to your ftp server
$stream = stream_context_create(array('ftp' => array('overwrite' => true)));
//authenticate to your ftp server, normal uri syntax
$uri = sprintf('ftp://%s:%s#%s/%s', $user, $password, $host, $filename);
file_put_contents($uri, $content, 0, $stream);
In phpinfo(); you can look for Registered PHP Streams and just use this in most of any cases:
file_put_contents('ftp://user:password#server/your/directory/file.csv', $csvData);
ftp_fput is a right way here.
But you have to prepare FTP connection and authenticate first. Assuming you have $csv_export string in memory:
// connect
$ftp_conn = ftp_connect('ftp.yourserver.net');
// authenticate
$login_result = ftp_login($conn_id, 'ftp_username', 'password');
// prepare output stream
$stream = fopen('data://text/plain,' . $csv_export, 'r');
// try to upload
if (ftp_fput($ftp_conn, '/httpdocs/.../abandoned.csv', $stream, FTP_ASCII)) {
echo "Successfully uploaded\n";
} else {
echo "There was a problem while uploading\n";
}
// close the connection and the file handler
ftp_close($ftp_conn);
fclose($stream);
You're receiving that error because fopen is returning false, which indicates that it was unable to open the file.
If I'm understanding your code, you're uploading abandoned.csv (which presumably exists) to the ftp after opening it in $temp. Is $temp pointing at your local copy of abandon.csv? Because if so, you should close the file stream pointing to it before opening a second one with fopen.
If that's not the issue, then abandoned.csv may not actually exist, in which case you may just be trying to fopen a missing file.
Related
Today I'm battling against ssh with huge success if it wasn't for ssh2_scp_send() method. This is the first time I work integrating ssh with PHP, so you may find multiple erros in the code that I have yet to discover, since I am currently stuck at that part.
I am using a dummy array imitating the one I must get from a couple of forms and the auth is working fine, although I had a little problem back there given that I had to use 'root' as user for the public key to be recognised as correct when comparing against, instead of my actual user.
Once I solved that matter, I discovered that the code is not working properly, this time the console says:
ssh2_scp_send(tmp/sshPm/prueba1.csv): failed to open stream: No such file or directory in /home/josemaria/Desktop/API UBcloud/CSV/provisioning.php on line 32
Here is my code:
function arrayToCsv($array, $filename, $delimiter = ';'){
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="'.$filename.'";');
$f = fopen('/tmp/sshPm/'.$filename, 'r');
foreach ($array as $line) {
fputcsv($f, $line, $delimiter);
}
}
function connectSsh($filename){
$sshConnection = ssh2_connect($host, $port);
if (!$sshConnection) {
die('Conexión Fallida');
}
ssh2_auth_pubkey_file($sshConnection, $user, $pubKey, $priKey);
ssh2_scp_send($sshConnection, "/tmp/sshPm/$filename", '/home/scripts/CSV', 0644);
$stream = ssh2_exec($sshConnection, "/home/scripts/sc_prov_ovpn_firm.sh $filename");
ssh2_exec($sshConnection, 'exit');
return $stream;
}
for ($i=0; $i < 10; $i++) {
$array[] = array(
"VAAAAAGH",
"THE WAGH IS HERE",
200 + $i,
564451 +$i,
"sip",
"",
"",
"",
"8.8.8.8",
"8.8.4.4",
20048,
"Modelo Terminal",
"677shdG3"
);
}
$filename = 'test.csv';
arrayToCsv($array, $filename);
$stream = connectSsh($filename);
print_r($stream);
As you can see, I intend the CSV's to be created and stored in /tmp. Even though the csv is created and placed in the right directory, whenever I reach scp_send, this method proves incapabe of finding it. I don't know if this could be related to the fact that I am using root to veify my public key as I've seen that it should be the user you are logged in with.
I also get the following warning right inmediately, but I guess this is consecuence of the first one... In any case, here it is:
PHP Warning: ssh2_scp_send(): Unable to read source file in /home/josemaria/Desktop/API UBcloud/CSV/provisioning.php on line 32.
I have tried using a wrapper instead of fopen() but with no success. As I said, this is the first time I work using ssh and PHP so I would ask you to explain a little bit at least!
Thank you so much for the help!
UPDATE
I managed to solve partially the issue by following ArSeN's advice and creating a directory in /Desktop and changing all the routes to that one, instead of /tmp. Now the problem I face is that I am not sure where to place the files once created. So my next question related to this issue would be:
Where should I store all the CSV's generated locally? As you see, I am doing it in /Documents since I have no restrictions there to read/modify, but I would say the answer lies in /, maybe /var? I really have no clue about much of this stuff...
Thank you again for the help provided!
This is what my code looks like now:
function arrayToCsv($array, $filename, $delimiter = ','){
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="'.$filename.'";');
$f = fopen("/home/josemaria/Documents/sshPm/$filename", 'w');
foreach ($array as $line) {
fputcsv($f, $line, $delimiter);
}
fclose($f);
}
function connectSsh($filename){
$sshConnection = ssh2_connect($host, $port);
if (!$sshConnection) {
die('Conexión Fallida');
}
ssh2_auth_pubkey_file($sshConnection, $user, $pubKey, $priKey);
ssh2_scp_send($sshConnection, "/home/josemaria/Documents/sshPm/$filename", "/home/scripts/CSV/$filename", 0644);
$stream = ssh2_exec($sshConnection, "/home/scripts/sc_prov_ovpn_firm.sh $filename");
ssh2_exec($sshConnection, 'exit');
return $stream;
}
for ($i=0; $i < 10; $i++) {
$array[] = array(
"VAAAAAGH",
"THE WAGH IS HERE",
200 + $i,
564451 +$i,
"sip",
"",
"",
"",
"8.8.8.8",
"8.8.4.4",
20048,
"Modelo Terminal",
"677shdG3"
);
}
$filename = 'test.csv';
arrayToCsv($array, $filename);
$stream = connectSsh($filename);
print_r($stream);
You should close the file handler so the file does actually get written and is not in some I/O buffer.
function arrayToCsv($array, $filename, $delimiter = ';'){
// all your existing code here ...
fclose($f);
}
Also with your copy target it seems like you are putting a file where a folder is before, meaning:
ssh2_scp_send($sshConnection, "/tmp/sshPm/$filename", '/home/scripts/CSV', 0644);
should probably be:
ssh2_scp_send($sshConnection, "/tmp/sshPm/$filename", "/home/scripts/CSV/$filename", 0644);
The answer to my issue had to do with permissions. I had some other errors as #ArSeN pointed out, but the warning I got and which prevented the code to work was because I was trying to store and read the files in /tmp withouth the permissions required to do so. So give yourself full permissions on the dir or change the dir for another. I still have some problems and issues with this code, but I do feel that they belong to a separate question that I will be linking here: How can I generate a CSV on Win and Linux using PHP and ProcessMaker? Which paths are reccommended to store the files locally?
I need to generate a CSV file from a MySQL query and save the file to an SFTP server. I have tried the code below. The CSV file gets created, but it is empty. I also receive an error message in the browser that says Warning: is_file() expects parameter 1 to be a valid path, resource given in regard to this line $sftp->put($fileName, $fp, NET_SFTP_LOCAL_FILE);. If I move fclose($fp); to the last line, I don't get the error but data still doesn't appear in the file. Could someone please let me know how to get the data to save in the file that was created?
$fileName = 'dataFiles/reports/Report Summary/Report Summary.csv';
$sql = mysqli_query($db, "
SELECT *
FROM reports
WHERE reportID = 1
");
$fp = fopen('php://output', 'w');
$first = true;
while($row = mysqli_fetch_assoc($sql)){
if ($first) {
fputcsv($fp, array_keys($row));
$first = false;
}
fputcsv($fp, $row);
}
fclose($fp);
$sftp->put($fileName, $fp, NET_SFTP_LOCAL_FILE);
Try something like this:
<?php
$fp = fopen('php://temp', 'r+');
// do stuff
rewind($fp);
$sftp->put($filename, $fp);
phpseclib (assuming you're using a new enough version) will detect that the second parameter is a stream resource and will try to read from it accordingly.
The second argument is not a handle but the content directly.
I think you could do: stream_get_contents($fp); in the second argument.
$content = stream_get_contents($fp);
fclose($fp);
$sftp->put($fileName, $content, NET_SFTP_LOCAL_FILE);
I recently installed Apache, PHP and started working on a small project.
I have the following code.
<?php
$tim=time();
$ip=$_SERVER['REMOTE_ADDR'];
$ipadd=$tim."IPaddress".$ip;
$fp="user_log.txt";// file address
$myfilea = fopen($fp,"a");//open file
fwrite($myfilea,$ipadd.PHP_EOL);//add data to file
echo fread($myfilea,filesize($fp));//read file
fclose($myfilea);//close file
?>
Here is what I can do... I can either use "a" mode to add text or I can use "r" mode to read text. I cant do both. I tried using "a+","r+","ar" etc.
Did I miss something during my setup ???
I am running this on windows 8.1.
Thanks for your help.
You need to rewind the file pointer.
$tim = time();
$ip = $_SERVER['REMOTE_ADDR'];
$ipadd = $tim.'IPaddress'.$ip;
// file address
$fp = 'user_log.txt';
//open file
$myfilea = fopen($fp, 'a+');
//add data to file
fwrite($myfilea, $ipadd.PHP_EOL);
// your file pointer is at the end of the file now
// so rewind before you read
rewind($myfilea);
//read file
echo fread($myfilea, filesize($fp));
//close file
fclose($myfilea);
Try this code, use file_put_contents
file_put_contents = Write a string to a file
$fp="user_log.txt";
$tim=time();
$ip=$_SERVER['REMOTE_ADDR'];
$ipadd=$tim."IPaddress".$ip;
$myfile = file_put_contents($fp, $ipadd.PHP_EOL , FILE_APPEND | LOCK_EX);
And for your code try this, it will check able to open file or not
fopen("logs.txt", "a") or die("Unable to open file!");
I have found a PHP script for transferring FTP files, and it works exactly as I need for one part of my project. The script can upload files via FTP to another server just fine, and can output the progress as it goes.
The code I am using is:
$fp = fopen($local_file, 'r');
$conn_id = ftp_connect($source_ftp_server);
$login_result = ftp_login($conn_id, $source_ftp_user_name, $source_ftp_user_pass);
$ret = ftp_nb_fput($conn_id, $remote_file, $fp, FTP_BINARY);
while ($ret == FTP_MOREDATA) {
// Establish a new connection to FTP server
if(!isset($conn_id2)) {
$conn_id2 = ftp_connect($source_ftp_server);
$login_result2 = ftp_login($conn_id2, $source_ftp_user_name, $source_ftp_user_pass);
}
// Retreive size of uploaded file.
if(isset($conn_id2)) {
clearstatcache(); // <- this must be included!!
$remote_file_size = ftp_size($conn_id2, $remote_file);
}
// Calculate upload progress
$local_file_size = filesize($local_file);
if (isset($remote_file_size) && $remote_file_size > 0 ){
$i = ($remote_file_size/$local_file_size)*100;
printf("%d%% uploaded<br>", $i);
flush();
}
$ret = ftp_nb_continue($conn_id);
}
if ($ret != FTP_FINISHED) {
echo "<span style='color:red;'><b>There was an error uploading the file...</b></span><br>";
exit(1);
}
else {
echo "<br>Files successfully uploaded!<br><br>";
}
fclose($fp);
I took out some unimportant parts, such as extra information that is echoed by the script, etc.
This code works perfectly for uploading files to the other server. However, I also need to download a file from the server using FTP as well.
I'd really like to use the same code as above, with the progress indicator, etc, but am not sure how to modify this code to download a file instead of uploading one.
It may be a couple of simple changes are all that is needed.
Are there any parts of this code in particular that will need to be changed, or can this not work the same for downloads as it does for uploads?
I'd really appreciate it if someone could point me in somewhat of the right direction to sort this out.
Is it as simple as changing the ftp_nb_fput command to a ftp_nb_get command? I don't really understand all of this code so it's difficult to tell what would need to be changed.
Thanks for your help.
You are looking for ftp_get
Looks like it should be used something like the following:
$conn_id = ftp_connect($source_ftp_server);
$login_result = ftp_login($conn_id, $source_ftp_user_name, $source_ftp_user_pass);
$success = ftp_get($conn_id, $local_file, $server_file, FTP_BINARY);
http://php.net/manual/en/function.ftp-get.php
Here's the script, with the necessary modifications to make it download a file instead:
$fp = fopen($local_file2, 'w+');
$conn_id = ftp_connect($source_ftp_server);
$login_result = ftp_login($conn_id, $source_ftp_user_name, $source_ftp_user_pass);
$ret = ftp_nb_fget($conn_id, $fp, $remote_file2, FTP_BINARY);
while ($ret == FTP_MOREDATA) {
// Establish a new connection to FTP server
if(!isset($conn_id2)) {
$conn_id2 = ftp_connect($source_ftp_server);
$login_result2 = ftp_login($conn_id2, $source_ftp_user_name, $source_ftp_user_pass);
}
// Retreive size of source file.
if(isset($conn_id2)) {
clearstatcache(); // <- this must be included!!
$remote_file2_size = ftp_size($conn_id2, $remote_file2);
}
// Calculate download progress
$local_file2_size = filesize($local_file2);
if (isset($remote_file2_size) && $remote_file2_size > 0 ){
$i = ($local_file2_size/$remote_file2_size)*100;
printf("%d%% downloaded<br>", $i);
}
$ret = ftp_nb_continue($conn_id);
}
if ($ret != FTP_FINISHED) {
echo "<span style='color:red;'><b>There was an error downloading the file...</b></span><br>";
exit(1);
}
echo "<br>Files successfully downloaded!<br><br>";
fclose($fp);
I've been struggling with writing a single string into a file.
I'm using just a simple code under Slackware 13:
$fp = fopen('/my/absolute/path/data.txt', 'w');
fwrite($fp, 'just a testing string...');
fclose($fp);
The file gets created (if it's not already created) but it's empty ?!
The directory in which this file is written is owned by apache's user & group (daemon.daemon) and has 0777 permissions.
This has never happened to me before. I'm curious what's the reason I'm not able to write inside the file ?
Thanks in advance.
Try $ df -h
It probably means your disk is full.
In my opinion you could check the return values:
$fp = fopen('/my/absolute/path/data.txt', 'w');
// $fp -> manual: "Returns a file pointer resource on success, or FALSE on error."
if ($fp) {
$bytes_written = fwrite($fp, 'just a testing string...');
if ($bytes_written) {
echo "$bytes_written bytes written!\n";
} else {
echo "Error while writing!\n"
}
$success = fclose($fp);
if ($success) {
echo "File successfully closed!\n";
} else {
echo "Error on closing!\n";
}
} else {
echo "No filepointer ressource!\n";
}
I suggest using file_put_conents($file_name, $file_cotents);
And to retrieve content: file_get_contents($file_name);
Code looks cleaner too.
http://php.net/manual/en/function.file-put-contents.php and
http://www.php.net/manual/en/function.file-get-contents.php
Could be something is happening to the script/file before the file is closed. Check if there are any other processes that try to access the file (you can use lsof). Also try writing to a new file to see if the same thing occurs.
Also, check the return value on fclose() to make sure the file is being closed successfully.