I need to read a list of CSV files from an FTP and delete them after I successfully read them.
Until now, i opened the csv file using fopen into a resource and then used fgetcsv to read the csv lines from it.
$res = fopen($url);
while ($csv_row = fgetcsv($res, null, self::DELIMITER)) {
.....
}
The problem is that I need to read a list of csv files and delete them too. the ftp_get function save the file into a local file. I rather avoid that. any way I can keep using the fgetcsv function with the ftp_nlist & ftp_connect functions? ?
You can save the csv file to a temporary file stream using ftp_fget(). This allows you to avoid the "create-read-delete" cycle. Once you close the file stream it's like it magically never existed :)
$ftp_handle = ftp_connect($ftp_server);
$remote_path = "/path/to/file.csv";
$tmp_handle = fopen('php://temp', 'r+');
if (ftp_fget($ftp_handle, $tmp_handle, $remote_path, FTP_ASCII)) {
rewind($tmp_handle);
while ($csv_row = fgetcsv($tmp_handle)) {
// do stuff
}
}
fclose($tmp_handle);
If you wanted to loop over a directory of files just get the list of files and then put the above code in a loop.
Related
I use a custom CMS in PHP and I need to let admin user to save a global configuration option for his website.
I would like to store this value into a file.
Avoiding to save it into mysql DB, so I don't need to do an extra query on every page load.
What is the best way to store this option from a form into a file?
I need to reload my saved setting so it can be edited with my form
Ini file format simple enough for anyone to understand (read). You might want to paste the file's content into a textarea for simple edition.
For advanced edition, you can use parse_ini_file http://php.net/manual/en/function.parse-ini-file.php .
here is the code to open a php file using php :
$file = "/home/dir/file.php";
$fs = fopen( $file, "a+" ) or die("error when opening the file");
while (!feof($fs)) {
$contents .= fgets($fs, 1024);
}
fclose($fs);
now you can take the $contents and modify it to however you would like and then save it. here is how you can save it :
$fs = fopen( $_POST["file"], "a+" ) or die("error when opening the file");
fwrite($fs, $updatedContents);
fclose();
$updatedContents
is the updated content
how to update a php file's source code via another php file
I have cleanup script, which move the XLS files from one place to another. for this file moving process, I have used the rename function. This script is working fine. but when the XLS file is open, when I try to move that xls, I am getting error which simply say Can not rename sample.xls. But I would like to add the functionality like, Check the XLS is open before initiate rename function.
I believe this is function call flock but this is applicable for TXT file alone.
How to check XLS file is opened before call the rename function.
One simple thing you could try is to use flock to acquire a Exclusive Lock on the file and if it fails you will know the file is being used:
<?php
$fp = fopen('c:/your_file.xlsx', 'r+');
if(!flock($fp, LOCK_EX))
{
echo 'File is being used...';
exit(-1);
}
else
{
fclose($fp);
// rename(...);
}
An alternative would be to check the existence of the locking file excel usually creates when a file is being used:
<?php
$file = 'c:/testfile.xlsx';
$lock = 'c:/~$testfile.xlsx';
if (file_exists($lock))
{
echo "Excel $file is locked.";
}
else
{
echo "Excel $file is free.";
}
The hidden file is usually name with the prefix ~$ as for old excel files I believe 2003 and older the lock files are saved on the temp folder with a random name like ~DF7B32A4D388B5854C.TMP so it would be pretty hard to find out.
You should use flock(). This puts a flag on the file so that other scripts are informed that the file is in use. The flag is turned off either intentionally using fclose or implicitly by the end of the script.
Use file lock like:
flock($file,LOCK_EX);
see this
I have a processing server with my database and a serving database to serve up files with a low bandwidth cost. On the processing server, php is not able to create files so everything must be done with streams and/or stay in memory before being sent over to another server for download. A few days ago I found out about the stream abstraction with 'php://memory' and that I can do something like
$fp=fopen('php://memory','w+');
fwrite($fp,"Hello world");
fseek($fp,0,SEEK_SET);
//make a ftp connection here with $conn_id
$upload = ftp_fput($conn_id,"targetpath/helloworld.txt",$fp,FTP_BINARY);
to make the file in memory and then allow me to ftp it over to my other server. This is exactly what I want, except I also want to zip the data before sending it -- preferably using only native parts of php like ziparchive and not additional custom classes for special stream manipulation. I know that I am very close with the following...
$zip = new ZipArchive();
if($zip->open('php://memory', ZIPARCHIVE::CREATE)) {
$zip->addFromString('testtext.txt','Hello World!');
$fp = $zip->getStream('test'); if(!$fp) print "no filepointer";
//make a ftp connection here with $conn_id
$upload = ftp_fput($conn_id,"targetpath/helloworld.zip",$fp,FTP_BINARY);
} else print "couldn't open a zip like that";
The point at which this fails is the call to getStream (which always returns false although I think I am using correctly). It appears that the zip is fine making the file in 'php://memory' but for some reason getStream still fails although perhaps I don't sufficiently understand how ZipArchive makes zips...
How can I go from the string to the zipped filepointer so that I can ftp the zip over to my other server? Remember I can't make any files or else I would just make the zip file then ftp it over.
EDIT: based on skinnynerd's suggestions below I tried the following
$zip = new ZipArchive();
if($zip->open('php://memory', ZIPARCHIVE::CREATE)) {
$zip->addFromString('testtext.txt','Hello World!');
$zip->close();
$fp = fopen('php://memory','r+');
fseek($fp,0,SEEK_SET);
//connect to ftp
$upload = ftp_fput($conn_id,"upload/transfer/helloworld.zip",$fp,FTP_BINARY);
}
This does make a zip and send it over but the zip is 0 bytes large so I don't think that 'php://memory' works the way I thought... it actually fails at the close step -- the $zip->close() returns false which makes me wonder if I can open zips into 'php://memory' at all. Does anyone know what I can try along these line to get the zip?
$zip->getStream('test') is getting a stream to extract the file 'test' from the archive. Since there's no file 'test' in the archive, this fails. This is not the function you want to use.
As you said, what you want to do is send the finished archive to the ftp server. In this case, you would want to close the zip archive, and then reopen php://memory as a normal file (using fopen) to send it.
I don't know, but you may also be able to use $zip as a resource directly, without having to close and reopen the file.
And I think you can try create a stream pipe directly from ftp server
<?php
$zip = new ZipArchive();
if($zip->open('ftp://user:password#ftp.host.com/upload/transfer/helloworld.zip', ZipArchive::CREATE))
{
$zip->addFromString('testtext.txt','Hello World!');
$zip->close();
}
else
print "couldn't open zip file on remote ftp host.";
Does it have to be a Zip archive? Since you're trying to save bandwith it could be a gzip too.
<?php
$ftp_credentials = "ftp://USER:PASSWORD#HOST/helloworld.gz";
$gz = gzencode("Hello World!", 9);
$options = array('ftp' => array('overwrite' => true));
$stream_context = stream_context_create($options);
file_put_contents($ftp_credentials, $gz, 0, $stream_context);
?>
So, I'm trying to copy a file from my local server to a remote server with FTP. The problem is, I need to do this in chunks.
Thus far, based on my research, it looks like it will probably be easiest to do this by making two files on my local server: the file to be copied, and a small, temporary file that holds the current chunk. Then, I should simply merge that chunk with the remote file.
The problem is, I'm having trouble appending files. I can't figure out how the ftp:// protocol works, and I can't find a comprehensive explanation on how to do it with cURL. The closest I've found is this, but I couldn't get it working.
Below is what I've written up so far. I've commented it so you can just skim through it to get the idea, and see where I'm stuck--the code isn't complicated. What do you recommend I do? How do I append a file on my local server a file on a remote server with FTP?
<?php
// FTP credentials
$server = HIDDEN;
$username = HIDDEN;
$password = HIDDEN;
// Connect to FTP
$connection = ftp_connect($server) or die("Failed to connect to <b>$server</b>.");
// Login to FTP
if (!#ftp_login($connection, $username, $password))
{
echo "Failed to login to <b>$server</b> as <b>$username</b>.";
}
// Destination file (where the copied file should go)
$destination = 'final.txt';
// The file on my server that we're copying (in chunks) to $destination.
$read = 'readme.txt';
// Current chunk of $read.
$temp = 'temp.tmp';
// If the file we're trying to copy exists...
if (file_exists($read))
{
// Set a chunk size (this is tiny, but I'm testing
// with tiny files just to make sure it works)
$chunk_size = 4;
// For reading through the file we want to copy to the FTP server.
$read_handle = fopen($read, 'r');
// For writing the chunk to its own file.
$temp_handle = fopen($temp, 'w+');
// Loop through $read until we reach the end of the file.
while (!feof($read_handle))
{
// Read a chunk of the file we're copying.
$chunk = fread($read_handle, $chunk_size);
// Write that chunk to its own file.
fwrite($temp_handle, $chunk);
////////////////////////////////////////////
//// ////
//// NOW WHAT?? HOW DO I ////
//// WRITE / APPEND THAT ////
//// CHUNK TO $destination? ////
//// ////
////////////////////////////////////////////
}
}
fclose($read_handle);
fclose($temp_handle);
ftp_close($ftp_connect);
?>
First off i don't think you need to create the tmp file. You can append to the destination file either using "append mode" (a) as defined in the manual or use file_put_contents with the FILE_APPEND flag.
file_put_contents does takes a filename as parameter not a file handle so it basically does fopen for you which means that if you write frequently it will fopen frequently which is less optimal compared to using the file handle ad fwrite.
<?php
// The URI of the remote file to be written to
$write = 'ftp://username1:password1#domain1.com/path/to/writeme.txt';
// The URI of the remote file to be read
$read = 'ftp://username2:password2#domain2.com/path/to/readme.txt';
if (file_exists($read)) // this will work over ftp too
{
$chunk_size = 4;
$read_handle = fopen($read, 'r');
$write_handle = fopen($write, 'a');
while (!feof($read_handle))
{
$chunk = fread($read_handle, $chunk_size);
fwrite($write_handle, $chunk);
}
}
fclose($read_handle);
fclose($write_handle);
?>
As a side note: PHP has stream wrappers that make ftp access a breeze without using the ftp functions themselves.
I am creating a flatfile database, and I am trying to solve the problem of multiple edits being made at the same time. I understand I need to truncate the file for editing and deleting rows but for adding rows this is not necessary.
So if I were to use fopen($file, 'a') to write to a file, and multiple people where to open the file and write to it, would they all be able to write to the file simultaneously?
Without truncating the file people shouldn't be overwriting each other right?
It's better to use some kind of helper for this.
PHP function flock (File LOCK)
//Open the File Stream
$handle = fopen($file,"a");
//Lock File, error if unable to lock
if(flock($handle, LOCK_EX)) {
$data;
// do anything to fill variable $data
fwrite($handle, $data); //Write the $data into file
flock($handle, LOCK_UN); //Unlock File
} else {
echo "Could not Lock File!";
}
//Close Stream
fclose($handle);
PHP file write threading issues
Read and write to a file while keeping lock