I'm using wget in a php script and need to get the name of the file downloaded.
For example, if I try
<?php
system('/usr/bin/wget -q --directory-prefix="./downloads/" http://www.google.com/');
?>
I will get a file called index.html in the downloads directory.
EDIT: The page will not always be google though, the target may be an image or stylesheet, so I need to find out the name of the file that was downloaded.
I'd like to have something like this:
<?php
//Does not work:
$filename = system('/usr/bin/wget -q --directory-prefix="./downloads/" http://www.google.com/');
//$filename should contain "index.html"
?>
Maybe that's some kind of cheating, but why not :
decide yourself the name of the file that wget should create
indicate to wget that the download should be made to that file
when the download is finished, use that file -- as you already know the name.
Check out the -O option of wget ;-)
For example, running this from the command-line :
wget 'http://www.google.com/' -O my-output-file.html
Will create a file called my-output-file.html.
if your requirement is simple like just getting google.com, then do it within PHP
$data=file_get_contents('http://www.google.com/');
file_put_contents($data,"./downloads/output.html");
On Linux like systems you can do:
system('/usr/bin/wget -q --directory-prefix="./downloads/" http://www.google.com/');
$filename = system('ls -tr ./downloads'); // $filename is now index.html
This works if there is no other process creating file in the ./downloads directory.
I ended up using php to find the most recently updated file in the directory using the following code:
<?php
system('/usr/bin/wget -q --directory-prefix="./downloads/" http://www.google.com/');
$dir = "./downloads";
$newstamp = 0;
$newname = "";
$dc = opendir($dir);
while ($fn = readdir($dc)) {
# Eliminate current directory, parent directory
if (ereg('^\.{1,2}$',$fn)) continue;
$timedat = filemtime("$dir/$fn");
if ($timedat > $newstamp) {
$newstamp = $timedat;
$newname = $fn;
}
}
// $newname contains the name of the most recently updated file
// $newstamp contains the time of the update to $newname
?>
Related
Two zip files and Two images are in https://example.com/directory. (Since index.php file is available in this directory we don't know the file names of those files).
Is there any possible way to find names of above four files using PHP or Linux commands?
You must keep in mind: if your web-server disallows to scan a directory then you couldn't get file names. But if the directory is shared in web-server you can get a list of files with using wget command. For example:
wget -nv -r -np '*.*' https://example.com/directory/
Say you have on your webserver example.com a directory like: /multimedia/ and you want to retrieve its contents like mp3, jpg, png, etc - but not the listing index nor tmp index files like i.e: index.html•C=D;O=D:
wget -r -R "*.html*" -np -nd -l 1 example.com/multimedia/
where:
-r # Recursive
-R "*.html*" # Reject tmp and listing html files
-np # Don't ascend to the parent directory
-nd # Don't create parent directories
-l 1 # Only one level deep (multimedia/ folder only)
To learn more: run man wget or wget --help or visit gnu.org WGET
<?php
$files=[];
$folder="/directory/directory/directory/";
if (is_dir($folder)){ // check whether exists or not
$allfiles = glob($folder.'/*.*'); // Read all filenames of $folder directory
foreach($allfiles as $imgFile) {
$files[]=$imgFile; // Putting the names of $folder directory to array one by one
}
}
echo "<pre>";
print_r($files); // printing the file name array to list aal names
echo "</pre>";
I think you don't understant HTTP protocals at all. According to HTTP protocal it doesn't know about any directory/sub-directory. You can't do things as such in HTTP Protocal.
You want to download http://example.com/directory some files for which you don't know the names. For that you can't use PHP as such. You have to depend on external library such as wget etc. or FTP protocal.
<?php
$dir = 'directory';
$filesArr = scandir($dir);
$files = array();
for($i=2; $i<count($filesArr);++$i){
if($filesArr[$i]=="index.php"){ continue; }
$files[] = $filesArr[$i];
}
$zipname = 'file1.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
$zip->addFile($dir.'/'.$file, $dir.'/'.$file);
}
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
$zip->close();
exit;
?>
Try this I am using below sample in my project and its working fine for me,
<?php
$directory='directory';
$handler= opendir("$directory"."/");
$i=0;
while (false !== ($file = readdir($handler))) {
if ($file != '.' && $file !='..'){
echo $file.'<br>';
}
}
?>
You can use PHPs scandir Method.
Try this:
<?php
$files = scandir('./');
print_r($files);
This should print all files in the current directory. More information here
EDIT: I'm pretty sure the issue has to do with the firewall, which I can't access. Marking Canis' answer as correct and I will figure something else out, possibly wget or just manually scraping the files and hoping no major updates are needed.
EDIT: Here's the latest version of the builder and here's the output. The build directory has the proper structure and most of the files, but only their name and extension - no data inside them.
I am coding a php script that searches the local directory for files, then scrapes my localhost (xampp) for the same files to copy into a build folder (the goal is to build php on the localhost and then put it on a server as html).
Unfortunately I am getting the error: Warning: copy(https:\\localhost\intranet\builder.php): failed to open stream: No such file or directory in C:\xampp\htdocs\intranet\builder.php on line 73.
That's one example - every file in the local directory is spitting the same error back. The source addresses are correct (I can get to the file on localhost from the address in the error log) and the local directory is properly constructed - just moving the files into it doesn't work. The full code is here, the most relevant section is:
// output build files
foreach($paths as $path)
{
echo "<br>";
$path = str_replace($localroot, "", $path);
$source = $hosted . $path;
$dest = $localbuild . $path;
if (is_dir_path($dest))
{
mkdir($dest, 0755, true);
echo "Make folder $source at $dest. <br>";
}
else
{
copy($source, $dest);
echo "Copy $source to $dest. <br>";
}
}
You are trying to use URLs to travers local filesystem directories. URLs are only for webserver to understand web requests.
You will have more luck if you change this:
copy(https:\\localhost\intranet\builder.php)
to this:
copy(C:\xampp\htdocs\intranet\builder.php)
EDIT
Based on your additional info in the comments I understand that you need to generate static HTML-files for hosting on a static only webserver. This is not an issue of copying files really. It's accessing the HMTL that the script generates when run through a webserver.
You can do this in a few different ways actually. I'm not sure exactly how the generator script works, but it seems like that script is trying to copy the supposed output from loads of PHP-files.
To get the generated content from a PHP-file you can either use the command line php command to execute the script like so c:\some\path>php some_php_file.php > my_html_file.html, or use the power of the webserver to do it for you:
<?php
$hosted = "https://localhost/intranet/"; <--- UPDATED
foreach($paths as $path)
{
echo "<br>";
$path = str_replace($localroot, "", $path);
$path = str_replace("\\","/",$path); <--- ADDED
$source = $hosted . $path;
$dest = $localbuild . $path;
if (is_dir_path($dest))
{
mkdir($dest, 0755, true);
echo "Make folder $source at $dest. <br>";
}
else
{
$content = file_get_contents(urlencode($source));
file_put_contents(str_replace(".php", ".html", $dest), $content);
echo "Copy $source to $dest. <br>";
}
}
In the code above I use file_get_contents() to read the html from the URL you are using https://..., which in this case, unlike with copy(), will call up the webserver, triggering the PHP engine to produce the output.
Then I write the pure HTML to a file in the $dest folder, replacing the .php with .htmlin the filename.
EDIT
Added and revised the code a bit above.
I have a very simple code, but the final command I can not apply it to the generated file, I can not rename the file and I don't know why. it is not a renaming issue because if I change the renaming for $cmd ="cp '$textfile''$file'" or $cmd ="mv '$textfile''$file'", it does not work either. I better explain it with the code:
<?php
// the original file to work with
$file = "COPYING.odt";
//change the extension of doc|pdf|docx|odt|rtf files to txt
$txtfile = preg_replace('"\.(doc|pdf|docx|odt|rtf)$"', '.txt', $file);
//convert the odt file into txt and name it with the original name but txt extension
$cmd = "/usr/bin/unoconv -f txt '$file' -o '$textfile'";
shell_exec($cmd);
//store the file in the originals files folder
rename("$file", "orig/$file");
//rename the generated txt file with the original name and extension "COPYING.odt"
rename("$textfile", "$file");
echo "conversion of file <em>$file</em> done";
?>
Any suggestions? Thanks.
UPDATE One thing I have forgoten to tell is that I apply this script to an uploaded file, so I can not give the static name of $file, but the variable $file.
UPDATE 2 Following #AlanMachado suggestion I've changed mv command for rename, and this rename works but not the next.
Sorry guys, I've been three days with this script, that's why I ask the question in Stackoverflow, but just now I've realised that it is a TYPO error, yes:
$txtfile = preg_replace('"\.(doc|pdf|docx|odt|rtf)$"', '.txt', $file);
txtfile without e in txt, while
rename("$textfile", "$file");
textfile with e in text, I'm really sorry.
Anyway I don't know why the results of this command was the file with the right name:
$cmd = "/usr/bin/unoconv -f txt '$file' -o '$textfile'";
I wrote a method to create a zip entry and rewrite it if this function is called second time but it is not working. here is my code:
public function zipFile($filepath,$fileName){
$zip = new ZipArchive;
$zip_name = $fileName.'.zip';
echo "$zip_name";
if($zip->open($zip_name, ZIPARCHIVE::OVERWRITE)===TRUE) {
$zip->addFile($filepath,$fileName.'.csv');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
return '/home/daily_reports/'.$zip_name;
}
what is missing in my logic. I want to replace the file with new one if the method is called again
Perhaps try explicitly deleting the zip file first if it exists. The overwrite option may not behave as expected.
clearstatcache();//For good measure clear out any cached file paths
$file = "{$filepath}/{$fileName}"
if(file_exists($file)){
unlink($file);
}
However, I have had mysterious issues trying to use the built-in zip functionality in php, especially with platform differences, performance, and memory issues. I prefer to zip the files on the command line through php.
On linux/osx:
$cmd = "zip archivefile file1 file2";
exec($cmd);
On windows use 7zip, also from the command line. http://www.dotnetperls.com/7-zip-examples
$cmd = "7za.exe a archivefile.7z file1 file2";
exec($cmd);
Technically you don't need to install 7zip, you just need the stand alone exe, but you might need to install it first to get the exe. http://www.7-zip.org/download.html
I am trying to make a cron job via my websites cpanel. I have talked to the support services and they gave me this command to run to execute a php file on my website.
/usr/local/bin/php -q /home/mymcstatus/domains/mymcstatus.net/public_html/redesign/scripts/update.php
This doesnt seem to work though, I have also set the minute interval to every minute using */1.
I am using the code below inside of the file update.php:
<?php
ini_set('display_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', dirname(__FILE__) . '/error_log.txt');
error_reporting(E_ALL);
require('minequery.class.php');
include('../config/config.php');
$date = date("D-M-Y");
$file = fopen("UPDATE_LOG($date).txt", 'w');
$query = mysql_query("SELECT * FROM servers") or die(mysql_error());
if($query) {
while($row = mysql_fetch_array($query)) {
$ip = $row['ip'];
$port = $row['port'];
$name = $row['name'];
$string = "[UPDATE LOG]: $date - Updated Server $name \n";
fwrite($file, $string);
print("[UPDATE LOG] Updated Server $name </br>");
}
mail("duncan#mymcstatus.net","UPDATED","Server has updated","From: Mymcstatus");
} else {
print("Cant query");
}
?>
When I go to update.php manually through the web browser that code works, but nothing seems to happen with the Cronjob. What am I missing or doing wrong?
There are a few things that could be going on here. The first is to check the file permissions of update.php and make sure it is executable. The cron may be executing as a different user that doesn't have permission to execute update.php. The 2nd thing you can try is including this as the very first line of update.php with no whitespace before it.
#!/usr/local/bin/php
Usually cron jobs aren't run from the same directory where your PHP lives so it's possible that it is running but the output file is being created elsewhere. Try changing the output file path to be the full path to the file, i.e:
$file = fopen("/home/mymcstatus/domains/mymcstatus.net/public_html/redesign/scripts/UPDATE_LOG($date).txt", 'w');
With the help of the above comments I managed to fix the file paths but it also came down to the command. I had put the wrong user path in here is the command that works.
/usr/local/bin/php -q /home/mymcstat/domains/mymcstatus.net/public_html/redesign/scripts/update.php
Thanks for the help
It's always a good idea to cd to your script's path. This way you don't need any change in the name of the include and require files and any other file names engaging in file operations. Your cronjob command could look like this:
cd /home/mymcstatus/domains/mymcstatus.net/public_html/redesign/scripts/; /usr/local/bin/php -q /home/mymcstatus/domains/mymcstatus.net/public_html/redesign/scripts/update.php
You don't need to supply any absolute file paths this way.