List and download clicked file from FTP
Your link in the generated <a>
tag points back to the web server, which does not contain the linked file.
What you need to do is to link to a PHP script, giving it a name of the file to download. The script will then download the file from an FTP server and pass the downloaded file back to the user (to the webbrowser).
echo "<a href=\"download.php?file=".urlencode($file)."\">".htmlspecialchars($file)."</a>";
A very trivial version of the download.php
script:
<?
header('Content-Type: application/octet-stream');
echo file_get_contents('ftp://username:password@ftp.example.com/path/' . $_GET["file"]);
The download.php
script uses FTP URL wrappers. If that's not allowed on your web server, you have to go the harder way with FTP functions. See
PHP: How do I read a file from FTP server into a variable?
Though for a really correct solution, you should provide some HTTP headers related to the file, like Content-Length
, Content-Type
and Content-Disposition
.
Also the above trivial example will first download whole file from the FTP server to the webserver. And only then it will start streaming it to the user (webbrowser). What is a waste of time and also of a memory on the webserver.
For a better solution, see Download file via PHP script from FTP server to browser with Content-Length header without storing the file on the web server.
You may also want to autodetect Content-Type
, unless all your files are of the same type.
A related question about implementing an FTP upload with a webpage:
Displaying recently uploaded images from remote FTP server in PHP
Get file list from FTP and download specific files
Once you downloaded the list of files like this:
$myList = ['0' => 'Report-important-20160613_134253.txt',
'1' => 'Report-important-20160614_102834.txt',
'2' => 'Report-important-20160615_112745.txt',
'3' => 'Report-important-20160616_082453.txt',
'4' => 'Report-important-20160617-034253.txt',
'5' => 'Report-important-20160618_142314.txt',
'6' => 'Time-20151126-152543.xls',
'7' => 'Extra-7d-20151210-135825.xls',
'8' => 'Report7d-20151215-110002.csv',
'9' => 'ReportPO-7d-20151210-151636.xls',
'10' => 'ReportPO-7d-20151213-210514.xls',
'11' => 'ReportPO -7d-20151214-074404.xls',
'12' => 'ReportPO -7d-20151215-075319.xls',
'13' => 'ReportPO -7d-20151216-080059.csv',
'14' => 'ReportPO -7d-20151217-075519.csv',
'15' => 'ReportPO -7d-20151218-075655.csv',
'16' => 'ReportPO -7d-20151219-080027.csv',
'17' => 'ReportPO -7d-20151220-075659.csv',
'18' => 'ReportPO -7d-20151221-075837.csv',
'19' => 'ReportPO -7d-20151222-074652.csv',
'20' => 'ReportPO -7d-20151223-081857.csv',
'21' => 'ReportTa-20151127-095630.xls'];
You know a lot. The lastest file starts with 'Report-important-20160618'
, which is: 'Report-important-'.date('Ymd')
. So all you have to do is look through the array, and get thoses files that match:
foreach ($myList as $filename) {
if (strpos($filename,'Report-important-'.date('Ymd')) !== FALSE) {
<... download $filename ...>
}
In other words: You don't need to know the time in the file to get a file for a certain date.
Download file from FTP server with list of paths and download each listed file
I ended up using PHP. Here is the working code :
1- Download the zip
$ftp_server = 'ftp.example.com';
$ftp_user_name = 'user';
$ftp_user_pass = 'psasword';
$remoteFilePath = '/data/photos.txt.zip';
$localFilePath = $_SERVER['DOCUMENT_ROOT']."/images";
// 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);
if ((!$conn_id) || (!$login_result)) {
echo 'FTP connection has failed! Attempted to connect to '. $ftp_server. ' for user '.$ftp_user_name.'.';
}else{
echo 'FTP connection was a success.<br>';
$directory = ftp_nlist($conn_id,'');
echo '<pre>'.print_r($directory,true).'</pre>';
$contents = ftp_nlist($conn_id, "/data/");
var_dump($contents);
$photos = ftp_nlist($conn_id, "/photos/");
var_dump($photos);
ftp_pasv($conn_id, true);
if (ftp_get($conn_id, $localFilePath.'/ddda-photos.txt.zip', $remoteFilePath, FTP_BINARY)) {
echo "File has been downloaded!!";
return true;
} else {
echo "fail ... ";
echo "Connected has be stopped!!";
return false;
}
}
2- Unzip the file
// assuming file.zip is in the same directory as the executing script.
$file = 'photos.txt.zip';
// get the absolute path to $file
$path = pathinfo(realpath($file), PATHINFO_DIRNAME);
$zip = new ZipArchive;
$res = $zip->open($file);
if ($res === TRUE) {
// extract it to the path we determined above
$zip->extractTo($path);
$zip->close();
echo "$file extracted to $path";
} else {
echo "Couldn't open $file";
}
3- Read the text file and download images
//So it doesn't time out
set_time_limit(0);
$ftp_server = 'ftp.example.com';
$ftp_user_name = 'user';
$ftp_user_pass = 'password';
$lines = file("photos.txt");
$dir = "F://test/";
//Goes through the file and separates name path and hash
foreach ($lines as $line) {
$parts = explode("\t", $line);
$imagePath = $parts[1];
$imageName = $parts[0];
$var1 = $ftp_server.trim($imagePath,'/');
$ftpUrl = 'ftp://'.$ftp_user_name.':'.$ftp_user_pass.'@'.$ftp_server.'/'.$imagePath;
// ftp url dump to be sure that something is happening
var_dump($ftpUrl);
$curl = curl_init();
$fh = fopen($dir.$imageName, 'w');
curl_setopt($curl, CURLOPT_URL, $ftpUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
fwrite($fh, $result);
fclose($fh);
curl_close($curl);
}
The problem was that for each request cURL had to pass the user and password in order to download the pictures.
Hope this helps someone with the same problem.
Downloading files from FTP site with specific words in the name
You are having problems getting the file list. LIST
returns a long-format listing with file attributes like for instance
-rw------- 1 td dialout 543 Apr 3 20:18 .bash_history
Use NLST
to get a short list. Also, the retrlines()
function is kinda strange. It calls a callback for each line (defaulting to print) it receives. The command only returns a status string. You can add your own callback to fill a list, or use the .nlst()
command to get the list for you.
from ftplib import FTP_TLS
import fnmatch
import os
ftps = FTP_TLS('myftp_site.com')
ftps.login('userxx', 'pwxx')
ftps.prot_p()
ftps.cwd('Inbox')
print("File list:")
list_of_files = []
ftps.retrlines("NLST", list_of_files.append)
# ...or use the existing helper
# list_of_files = ftps.nlst()
dest_dir = "C:\DownloadingDirectory"
for name in list_of_files:
if fnmatch.fnmatch(name,"StartingFileName*"):
with open(os.path.join(dest_dir, name), "wb") as f:
ftps.retrbinary("RETR {}".format(name), f.write)
ftps.quit()
Downloading list of files from remote FTP
Googling for EIdAcceptTimeout
leads to this discussion in the Indy forum:
UseHOST in TIdFTP (client) => EIdAcceptTimeout
Where Remy Lebeau states:
The only time that exception can occur during a data transfer is if
you have the TIdFTP.Passive property set to False, which tells the FTP
server to make an inbound connection to TIdFTP. Those connections are
usually blocked by firewalls/routers that are not FTP-aware. You
usually have to set TIdFTP.Passive=True when you are behind a
firewall/router.
So, the solution could be for you to add a line
oClientFTP.Passive := True;
Btw. In your code snippets you have both oClientFTP and oClienteFTP. Adjust my suggestion if needed.
Download files whose name contains a specific string from an FTP server
If I understand your question correctly, you want to download all files whose name contains "20201009" string, right?
$url = "ftp://ftp.example.com/remote/path/"
$credentials = New-Object System.Net.NetworkCredential("username", "password")
$request = [System.Net.WebRequest]::Create($url)
$request.Credentials = $credentials
$request.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectory
$response = $request.GetResponse()
$reader = New-Object IO.StreamReader $response.GetResponseStream()
$listing = $reader.ReadToEnd()
$reader.Close()
$response.Close()
$localpath = "C:\Users\Desktop\PowerShell"
$date = "20201009"
$files =
($listing -split "`r`n") |
Where-Object {$_ -like "*$date*"}
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = $credentials
foreach ($file in $files)
{
$localfilepath = (Join-Path $localPath $file)
Write-Host ($file + " => " + $localfilepath)
$webclient.DownloadFile(($url + $file), $localfilepath)
}
It's even easier, if you use WinSCP .NET assembly:
Add-Type -Path "WinSCPnet.dll"
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Ftp
HostName = "ftp.example.com"
UserName = "username"
Password = "password"
}
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
$localpath = "C:\Users\Desktop\PowerShell"
$date = "20201009"
$session.GetFilesToDirectory("/remote/path", $localpath, "*$date*").Check()
$session.Dispose()
(I'm the author of WinSCP)
Related Topics
Calling Function Inside Preg_Replace Thats Inside a Function
Type-Juggling and (Strict) Greater/Lesser-Than Comparisons in PHP
Getting Last Month's Date in PHP
How to Use Class Methods as Callbacks
Get the Last Modified Date of a Remote File
Pdo Fetchall Array to One Dimensional
Http_Build_Query with Same Name Parameters
How to Embed Images in a Single HTML/PHP File
Output Is in Seconds. Convert to Hh:Mm:Ss Format in PHP
How to Remove Attributes from an HTML Tag
Efficiently Pick N Random Elements from PHP Array (Without Shuffle)
Use PHP Composer to Clone Git Repo
How to Switch from Post to Get in PHP Curl
PHP Function Use Variable from Outside
How to Test If a User Has Selected a File to Upload
Regex for Checking If a String Has Mismatched Parentheses
Should I Use Prepared Statements for MySQL in PHP Performance-Wise