On FTP server has some files. For any hour on this server is uploading new files. I'd like to download last file. How can I get last uploaded file from this server? All files are with different names.
I used folowing script to downloading one file.
$conn = ftp_connect("ftp.testftp.com") or die("Could not connect");
ftp_login($conn,"user","pass");
ftp_get($conn,"target.txt","source.txt",FTP_ASCII);
ftp_close($conn);
Thanks in advance !!!
There is no way to be sure which file is the most recent, as there is no such thing as an "uploaded time" attribute. You didn't mention much about the FTP server, but if you have some level of management over the uploads, you could ensure that the last modified time is set on upload. Whether this ends up working is down to your FTP server and possibly clients.
Assuming your modified times are equivalent to upload times, you could do something like this:
// connect
$conn = ftp_connect('ftp.addr.com');
ftp_login($conn, 'user', 'pass');
// get list of files on given path
$files = ftp_nlist($conn, '');
$mostRecent = array(
'time' => 0,
'file' => null
);
foreach ($files as $file) {
// get the last modified time for the file
$time = ftp_mdtm($conn, $file);
if ($time > $mostRecent['time']) {
// this file is the most recent so far
$mostRecent['time'] = $time;
$mostRecent['file'] = $file;
}
}
ftp_get($conn, "target.txt", $mostRecent['file'], FTP_ASCII);
ftp_close($conn);
ftp_rawlist($conn);
extract latest filename and get it.
Related
How can I check if a specific file exists on a remote server using PHP via FTP connections?
Some suggestions:
Use ftp_size, which returns -1 if it doesn't exist: http://www.php.net/manual/en/function.ftp-size.php
Use fopen, e.g. fopen("ftp://user:password#example.com/somefile.txt", "r")
Use ftp_nlist, check to see if the filename you want is in the list: http://www.php.net/manual/en/function.ftp-nlist.php
I used this, a bit easier:
// the server you wish to connect to - you can also use the server ip ex. 107.23.17.20
$ftp_server = "ftp.example.com";
// set up a connection to the server we chose or die and show an error
$conn_id = ftp_connect($ftp_server) or die("Couldn't connect to $ftp_server");
ftp_login($conn_id,"ftpserver_username","ftpserver_password");
// check if a file exist
$path = "/SERVER_FOLDER/"; //the path where the file is located
$file = "file.html"; //the file you are looking for
$check_file_exist = $path.$file; //combine string for easy use
$contents_on_server = ftp_nlist($conn_id, $path); //Returns an array of filenames from the specified directory on success or FALSE on error.
// Test if file is in the ftp_nlist array
if (in_array($check_file_exist, $contents_on_server))
{
echo "<br>";
echo "I found ".$check_file_exist." in directory : ".$path;
}
else
{
echo "<br>";
echo $check_file_exist." not found in directory : ".$path;
};
// output $contents_on_server, shows all the files it found, helps for debugging, you can use print_r() as well
var_dump($contents_on_server);
// remember to always close your ftp connection
ftp_close($conn_id);
Functions used: (thanks to middaparka)
Login using ftp_connect
Get the remote file list via ftp_nlist
Use in_array to see if the file was present in the array
Just check the size of a file. If the size is -1, it doesn't exist, so:
$file_size = ftp_size($ftp_connection, "example.txt");
if ($file_size != -1) {
echo "File exists";
} else {
echo "File does not exist";
}
If the size is 0, the file does exist, it's just 0 bytes.
Source
A general solution would be to:
Login using ftp_connect
Navigate to the relevant directory via ftp_chdir
Get the remote file list via ftp_nlist or ftp_rawlist
Use in_array to see if the file was present in the array returned by ftp_rawlist
That said, you could potentially simply use file_exists if you have the relevant URL wrappers available. (See the PHP FTP and FTPS protocols and wrappers manual page for more information.)
This is an optimization of #JohanPretorius solution, and an answer for comments about "slow and inefficient for large dirs" of #Andrew and other: if you need more than one "file_exist checking", this function is a optimal solution.
ftp_file_exists() caching last folder
function ftp_file_exists(
$file, // the file that you looking for
$path = "SERVER_FOLDER", // the remote folder where it is
$ftp_server = "ftp.example.com", //Server to connect to
$ftp_user = "ftpserver_username", //Server username
$ftp_pwd = "ftpserver_password", //Server password
$useCache = 1 // ALERT: do not $useCache when changing the remote folder $path.
){
static $cache_ftp_nlist = array();
static $cache_signature = '';
$new_signature = "$ftp_server/$path";
if(!$useCache || $new_signature!=$cache_signature)
{
$useCache = 0;
//$new_signature = $cache_signature;
$cache_signature = $new_signature;
// setup the connection
$conn_id = ftp_connect($ftp_server) or die("Error connecting $ftp_server");
$ftp_login = ftp_login($conn_id, $ftp_user, $ftp_pwd);
$cache_ftp_nlist = ftp_nlist($conn_id, $path);
if ($cache_ftp_nlist===FALSE)die("erro no ftp_nlist");
}
//$check_file_exist = "$path/$file";
$check_file_exist = "$file";
if(in_array($check_file_exist, $cache_ftp_nlist))
{
echo "Found: ".$check_file_exist." in folder: ".$path;
}
else
{
echo "Not Found: ".$check_file_exist." in folder: ".$path;
};
// use for debuging: var_dump($cache_ftp_nlist);
if(!$useCache) ftp_close($conn_id);
} //function end
//Output messages
echo ftp_file_exists("file1-to-find.ext"); // do FTP
echo ftp_file_exists("file2-to-find.ext"); // using cache
echo ftp_file_exists("file3-to-find.ext"); // using cache
echo ftp_file_exists("file-to-find.ext","OTHER_FOLDER"); // do FTP
You can use ftp_nlist to list all the files on the remote server. Then you should search into the result array to check if the file what you was looking for exists.
http://www.php.net/manual/en/function.ftp-nlist.php
The code has been written by: #Drmzindec should be change a little:
if (in_array($check_file_exist, $contents_on_server))
to
if (in_array($file, $contents_on_server))
I'm struggling around with a simple PHP functionality: Creating a ZIP Archive with some files in.
The problem is, it does not create only one file called filename.zip but two files called filename.zip.a07600 and filename.zip.b07600. Pls. see the following screenshot:
The two files are perfect in size and I even can rename each of them to filename.zip and extract it without any problems.
Can anybody tell me what is going wrong???
function zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path = array(), $files_array = array()) {
// Archive File Name
$archive_file = $archiveDir."/".$archive_file_name;
// Time-to-live
$archiveTTL = 86400; // 1 day
// Delete old zip file
#unlink($archive_file);
// Create the object
$zip = new ZipArchive();
// Create the file and throw the error if unsuccessful
if ($zip->open($archive_file, ZIPARCHIVE::CREATE) !== TRUE) {
$response->res = "Cannot open '$archive_file'";
return $response;
}
// Add each file of $file_name array to archive
$i = 0;
foreach($files_array as $value){
$expl = explode("/", $value);
$file = $expl[(count($expl)-1)];
$path_file = $file_path[$i] . "/" . $file;
$size = round((filesize ($path_file) / 1024), 0);
if(file_exists($path_file)){
$zip->addFile($path_file, $file);
}
$i++;
}
$zip->close();
// Then send the headers to redirect to the ZIP file
header("HTTP/1.1 303 See Other"); // 303 is technically correct for this type of redirect
header("Location: $archive_file");
exit;
}
The code which calls the function is a file with a switch-case... it is called itself by an ajax-call:
case "zdl":
$files_array = array();
$file_path = array();
foreach ($dbh->query("select GUID, DIRECTORY, BASENAME, ELEMENTID from SMDMS where ELEMENTID = ".$osguid." and PROJECTID = ".$osproject.";") as $subrow) {
$archive_file_name = $subrow['ELEMENTID'].".zip";
$archiveDir = "../".$subrow['DIRECTORY'];
$files_array[] = $archiveDir.DIR_SEPARATOR.$subrow['BASENAME'];
$file_path[] = $archiveDir;
}
zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path, $files_array);
break;
One more code... I tried to rename the latest 123456.zip.a01234 file to 123456.zip and then unlink the old 123456.zip.a01234 (and all prior added .a01234 files) with this function:
function zip_file_exists($pathfile){
$arr = array();
$dir = dirname($pathfile);
$renamed = 0;
foreach(glob($pathfile.'.*') as $file) {
$path_parts = pathinfo($file);
$dirname = $path_parts['dirname'];
$basename = $path_parts['basename'];
$extension = $path_parts['extension'];
$filename = $path_parts['filename'];
if($renamed == 0){
$old_name = $file;
$new_name = str_replace(".".$extension, "", $file);
#copy($old_name, $new_name);
#unlink($old_name);
$renamed = 1;
//file_put_contents($dir."/test.txt", "old_name: ".$old_name." - new_name: ".$new_name." - dirname: ".$dirname." - basename: ".$basename." - extension: ".$extension." - filename: ".$filename." - test: ".$test);
}else{
#unlink($file);
}
}
}
In short: copy works, rename didn't work and "unlink"-doesn't work at all... I'm out of ideas now... :(
ONE MORE TRY: I placed the output of $zip->getStatusString() in a variable and wrote it to a log file... the log entry it produced is: Renaming temporary file failed: No such file or directory.
But as you can see in the graphic above the file 43051221.zip.a07200 is located in the directory where the zip-lib opens it temporarily.
Thank you in advance for your help!
So, after struggling around for days... It was so simple:
Actually I work ONLY on *nix Servers so in my scripts I created the folders dynamically with 0777 Perms. I didn't know that IIS doesn't accept this permissions format at all!
So I remoted to the server, right clicked on the folder Documents (the hierarchically most upper folder of all dynamically added files and folders) and gave full control to all users I found.
Now it works perfect!!! The only thing that would be interesting now is: is this dangerous of any reason???
Thanks for your good will answers...
My suspicion is that your script is hitting the PHP script timeout. PHP zip creates a temporary file to zip in to where the filename is yourfilename.zip.some_random_number. This file is renamed to yourfilename.zip when the zip file is closed. If the script times out it will probably just get left there.
Try reducing the number of files to zip, or increasing the script timeout with set_time_limit()
http://php.net/manual/en/function.set-time-limit.php
I currently have a program that connects to an ftp directory, if it finds csv files, runs a script, then after the script has run on the files, it creates a back up folder with the date and moves the csv files to this newly created back up folder in the ftp directory.
However, if there are no csv files in the root directory, I do not want a backup folder to be created, as there are no files to move. I know the solution is probably really simple but I cannot seem to figure it out!
logMessage("Creating backups");
$ftp_connection = #ftp_connect($ftp_url, $ftp_port, 6000);
if(!#ftp_login($ftp_connection, $ftp_username, $ftp_password )) {
logMessage("Could not connect to FTP: [$ftp_url], with Username: [$ftp_username], and Password: [$ftp_password]");
die();
}
$date = date('Y_m_d_(His)');
$newBackup = $ftp_root."/".$ftp_backup."backup_$date";
if (ftp_mkdir($ftp_connection, $newBackup)) {
logMessage ("Successfully created [$newBackup\n]");
foreach($filesToProcess as $file){
$pathData = pathinfo($file);
if(isset($pathData['extension']) && $pathData['extension'] == 'csv'){
if(!#ftp_rename($ftp_connection,
$ftp_root.'/'.$file,
$newBackup."/".$file)
){
logMessage("Unable to move file: $file")
}
}
}
}
You have used, foreach($filesToProcess as $file) ,so in $filesToProcess it's array of files. you can use, count($filesToProcess) first count number of files, then if count>0 execute code.
// $csv = your checks for string ending to .csv
$ftp_files = ftp_nlist($ftp_connection, ".");
foreach ($ftp_files = $files) {
if ($files = $csv) {
// makedir
maybe something like this in very basic syntax. ftp_nlist returns an array of all files in a particular directory.
I've written a MySQL database backup script which store backup files in remote FTP server. It creates some folders in root named by database name, then in each of them it creates some folders named by current date (Format: yyyy-mm-dd), and it these folders it uploads the backup files named by exact time.
I also need to remove old second level folders (which are named by date); I mean the folders older than 4 days. This is the part I've problem with. I tried some codes with ftp_nlist and I could list folders with it, I also ftp_mdtm to get the creation date and compare it with expiration date. But the result was not okay. Here is my code:
...
$skip = array('.', '..', '.ftpquota', '.htaccess');
$expire_date = date('Y-m-d', strtotime('-4 days', time()));
$ff_list = ftp_nlist($con, $db_dir);
foreach($ff_list as $item)
{
if(in_array($item, $skip))
{
continue;
}
$mod_time = ftp_mdtm($con, $item);
if(strtotime($expire_date ) >= $mod_time)
{
ftp_rmdir($con, $item);
}
}
...
Please attend I need to remove the old folders with all of their contents, So I need the suitable remove command (I don't know if ftp_rmdir works properly).
your using the correct command ftp_rmdir
http://php.net/manual/en/function.ftp-rmdir.php
but i bet the problem is that this function, like rmdir, requires the directory be empty.
here's a recursive delete function WARNING! UNTESTED!
//credentials
$host = "ftp server";
$user = "username";
$pass = "password";
//connect
$handle = #ftp_connect($host) or die("Could not connect to {$host}");
//login
#ftp_login($handle, $user, $pass) or die("Could not login to {$host}");
function recursiveDelete($directory){
//try to delete
if( !(#ftp_rmdir($handle, $directory) || #ftp_delete($handle, $directory)) ){
//if the attempt to delete fails, get the file listing
$filelist = #ftp_nlist($handle, $directory);
//loop through the file list and recursively delete each file in the list
foreach($filelist as $file){
recursiveDelete($file);
}
//if the file list is empty, delete the directory we passed
recursiveDelete($directory);
}
}
Try this :
if(strtotime($expire_date ) >= strtotime($mod_time))
How can I check if a specific file exists on a remote server using PHP via FTP connections?
Some suggestions:
Use ftp_size, which returns -1 if it doesn't exist: http://www.php.net/manual/en/function.ftp-size.php
Use fopen, e.g. fopen("ftp://user:password#example.com/somefile.txt", "r")
Use ftp_nlist, check to see if the filename you want is in the list: http://www.php.net/manual/en/function.ftp-nlist.php
I used this, a bit easier:
// the server you wish to connect to - you can also use the server ip ex. 107.23.17.20
$ftp_server = "ftp.example.com";
// set up a connection to the server we chose or die and show an error
$conn_id = ftp_connect($ftp_server) or die("Couldn't connect to $ftp_server");
ftp_login($conn_id,"ftpserver_username","ftpserver_password");
// check if a file exist
$path = "/SERVER_FOLDER/"; //the path where the file is located
$file = "file.html"; //the file you are looking for
$check_file_exist = $path.$file; //combine string for easy use
$contents_on_server = ftp_nlist($conn_id, $path); //Returns an array of filenames from the specified directory on success or FALSE on error.
// Test if file is in the ftp_nlist array
if (in_array($check_file_exist, $contents_on_server))
{
echo "<br>";
echo "I found ".$check_file_exist." in directory : ".$path;
}
else
{
echo "<br>";
echo $check_file_exist." not found in directory : ".$path;
};
// output $contents_on_server, shows all the files it found, helps for debugging, you can use print_r() as well
var_dump($contents_on_server);
// remember to always close your ftp connection
ftp_close($conn_id);
Functions used: (thanks to middaparka)
Login using ftp_connect
Get the remote file list via ftp_nlist
Use in_array to see if the file was present in the array
Just check the size of a file. If the size is -1, it doesn't exist, so:
$file_size = ftp_size($ftp_connection, "example.txt");
if ($file_size != -1) {
echo "File exists";
} else {
echo "File does not exist";
}
If the size is 0, the file does exist, it's just 0 bytes.
Source
A general solution would be to:
Login using ftp_connect
Navigate to the relevant directory via ftp_chdir
Get the remote file list via ftp_nlist or ftp_rawlist
Use in_array to see if the file was present in the array returned by ftp_rawlist
That said, you could potentially simply use file_exists if you have the relevant URL wrappers available. (See the PHP FTP and FTPS protocols and wrappers manual page for more information.)
This is an optimization of #JohanPretorius solution, and an answer for comments about "slow and inefficient for large dirs" of #Andrew and other: if you need more than one "file_exist checking", this function is a optimal solution.
ftp_file_exists() caching last folder
function ftp_file_exists(
$file, // the file that you looking for
$path = "SERVER_FOLDER", // the remote folder where it is
$ftp_server = "ftp.example.com", //Server to connect to
$ftp_user = "ftpserver_username", //Server username
$ftp_pwd = "ftpserver_password", //Server password
$useCache = 1 // ALERT: do not $useCache when changing the remote folder $path.
){
static $cache_ftp_nlist = array();
static $cache_signature = '';
$new_signature = "$ftp_server/$path";
if(!$useCache || $new_signature!=$cache_signature)
{
$useCache = 0;
//$new_signature = $cache_signature;
$cache_signature = $new_signature;
// setup the connection
$conn_id = ftp_connect($ftp_server) or die("Error connecting $ftp_server");
$ftp_login = ftp_login($conn_id, $ftp_user, $ftp_pwd);
$cache_ftp_nlist = ftp_nlist($conn_id, $path);
if ($cache_ftp_nlist===FALSE)die("erro no ftp_nlist");
}
//$check_file_exist = "$path/$file";
$check_file_exist = "$file";
if(in_array($check_file_exist, $cache_ftp_nlist))
{
echo "Found: ".$check_file_exist." in folder: ".$path;
}
else
{
echo "Not Found: ".$check_file_exist." in folder: ".$path;
};
// use for debuging: var_dump($cache_ftp_nlist);
if(!$useCache) ftp_close($conn_id);
} //function end
//Output messages
echo ftp_file_exists("file1-to-find.ext"); // do FTP
echo ftp_file_exists("file2-to-find.ext"); // using cache
echo ftp_file_exists("file3-to-find.ext"); // using cache
echo ftp_file_exists("file-to-find.ext","OTHER_FOLDER"); // do FTP
You can use ftp_nlist to list all the files on the remote server. Then you should search into the result array to check if the file what you was looking for exists.
http://www.php.net/manual/en/function.ftp-nlist.php
The code has been written by: #Drmzindec should be change a little:
if (in_array($check_file_exist, $contents_on_server))
to
if (in_array($file, $contents_on_server))