List and Download Clicked File from Ftp

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



Leave a reply



Submit