So, I have a PHP script that is supposed to download images that the user inputs. However, if the user uploads a TXT file and it contains direct links to images, it should download the images from all the URLs in the file. My script seems to be working, although it seems that only the last file is downloaded while the others are stored as files containing no data.
Here's the portion of my script where it parses the TXT
$contents = file($file_tmp);
$parts = new SplFileObject($file_tmp);
foreach($parts as $line) {
$url = $line;
$dir = "{$save_loc}".basename($url);
$fp = fopen ($destination, 'w+');
$raw = file_get_contents($url);
file_put_contents($dir, $raw);
}
How do I make it download every URL from the TXT file?
When you iterate over an SplFileObject, you get the whole line, including whitespace. Your URL will thus be something like
http://example.com/_
(php seems to mangle the newline to an underscore) and thus you'll get an error for many URLs (some URLs will still work fine, since they contain the important information prior. For instance, Batch download URLs in PHP? works, but https://stackoverflow.com/_ does not). If an error occurs, file_get_contents will return false, and file_put_contents will interpret that like an empty string.
Also, the line $fp = fopen ($destination, 'w+'); is really strange. For one, since $destination is not defined, it would error anyways. Even if $destination is defined, you'll end up with lots of file handles and overwrite that poor file multiple times. You can just remove it.
To summarize, your code should look like
<?php
$file_tmp = "urls.txt";
$save_loc = "sav/";
$parts = new SplFileObject($file_tmp);
foreach($parts as $line) {
$url = trim($line);
if (!$url) {
continue;
}
$dir = "{$save_loc}".basename($url);
$raw = file_get_contents($url);
if ($raw === false) {
echo 'failed to donwload ' . $url . "\n";
continue;
}
file_put_contents($dir, $raw);
}
It looks like line
$parts = new SplFileObject($file_tmp);
isn't necessary as well as
$fp = fopen ($destination, 'w+');
file() function reads entire file into array. You just have call trim() on each array element to remove new line from characters. Following code should work properly:
<?php
$save_loc = './';
$urls = file('input.txt');
foreach($urls as $url) {
$url = trim($url);
$destination = $save_loc . basename($url);
$content = file_get_contents($url);
if ($content) {
file_put_contents($destination, $content);
}
}
Related
I am currently working an auto-content-generator script's sitemap. I got to know that google accept sitemap in simple text file that contains one URL per line.
so I created a file named 1.txt and wrote a script to add current page URL to 1.txt when a user visits.
test.php is:
$file = 'assets/sitemap/1.txt';
$url = "http://".$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI]."\n";
$file = fopen($file, 'a');
fwrite($file, $url);
fclose( $file );
This script writes the page URLto 1.txt every time someone hits the page. But the problem is, it creates too much duplicate links. So I want to add a filter to not add a string (URL in this case) if it already exists.
After surfing a while, I got a solution here (second snippet) that is resource friendly: PHP check if file contains a string
I made the following modification but it is not working (not adding anything at all):
$file = 'assets/sitemap/1.txt';
$url = "http://".$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI]."\n";
if(exec('grep '.escapeshellarg($url).' assets/sitemap/1.txt')) {}
else{
$file = fopen($file, 'a');
fwrite($file, $url);
fclose( $file );
}
This is hopefully easier to understand:
$file = 'assets/sitemap/1.txt';
$url = "http://".$_SERVER[HTTP_HOST].$_SERVER[REQUEST_URI]."\n";
$text = file_get_contents($file);
if(strpos($text, $url) === false) {
file_put_contents($file, $url, FILE_APPEND);
}
Read the file contents into a string $text using file_get_contents()
Check if $url is in the string $text using strpos()
If $url is not in the string $text, append the $url to the file using file_put_contents()
To count the total lines, you can start using file() to load the file lines into an array. Then check if the $url is in the array using in_array():
$lines = file($file);
$count = count($lines); // count the lines
if(!in_array($url, $text)) {
file_put_contents($file, $url, FILE_APPEND);
$count++; // if added, add 1 to count
}
I have a file (sites.txt) that has two entries:
http://www.url1.com/test1.xml
http://www.url2.com/test2
Whenever I execute the below PHP code, the 'url1.com' returns false, and the 'url2.com' is loaded into $xml. The odd part is that if I interchange the URLs in the file, i.e.
http://www.url2.com/test2
http://www.url1.com/test1.xml
It loads both. Both URLs are valid XML documents. Why does the order matter here?
Code:
if (file_exists('sites.txt')) {
$file_handle = fopen("sites.txt", "r");
while (!feof($file_handle)) {
$site = fgets($file_handle);
$xml[] = simplexml_load_file($site);
}
fclose($file_handle);
}
try changing your text file to a csv then explode contents of the file on the delimiter:
http://www.url1.com/test1.xml,
http://www.url2.com/test2
$file = fopen("sites.txt", "r");
$files = explode(",", $file);
Sounds like there are some other things going on in addition to this but that you may have that sorted out...
I'm writing some code that can read in from a .txt file a display it on a webpage.
I had problems in my initial code, in that it would read in any text and it would erase whatever was in the document.
My original code:
function readIn(){
$input = fopen("input.txt", "r"); //Open the file, save opened file in input
$line = fgets($input);
fclose($input);
return $line
}
It only started working once I put in a While loop to go through EVERY LINE
function readIn(){
$input = fopen("input.txt", "r"); //Open the file, save opened file in input
$fullText = ""; //Variable full text
while(!feof($input)){
$line = fgets($input);
$fullText = $fullText . $line;
}
fclose($input);
return $fullText;
}
echo readIn();
Use "file_get_contents" to read an entire file into a variable, and then output in whatever fashion you choose.
I have a script checking if a file exists:
function fileExists($url) {
$fh = fopen($url, 'r');
if (is_resource($fh)) {
fclose($fh);
return true;
}
return false;
}
Everything went right until I tried to uploaded files whose name contains white space. Call $url the file's url, when I put it in the browser, it displays correctly the file, but is_resource($fh) always returns false. Someone could help ?
Before $fh = fopen($url, 'r'); add this:
$parts = pathinfo($url);
$url = $parts['dirname'].'/'.rawurlencode($parts['basename']);
Btw, there is a PHP bug...
I am very new to php, and i have search and put together this script to convert text to csv and write the out put on the file.
$File = "/var/apache2/htdocs/loginS/host.txt";
$Handle = fopen($File,"r");
$Content = fread ($Handle,filesize ($File));
fclose($File);
fclose($Handle);
$Content = explode("\t", $Content);
foreach($Content as $Value) {
//echo $Value."|"; // till this line working
fwrite($save, $Value);
fclose($save);
}
the problem is when I try to write on the file. I got only one line.what is my error.
You are calling fclose() on the file in your loop that is writing records. fclose() closes the file handle so it is no longer valid and cannot be written to.
Move fclose($save); after the } that ends the foreach() with your content.
Also, you could simplify things a bit by calling $Content = file_get_contents($File); since that is what you are doing in effect with fread(). Also, since $File is just a string variable, calling fclose() on it is unnecessary and doesn't do anything. You were correctly closing it by calling fclose() on $Handle. But using file_get_contents() will eliminate the need for both. The only file you would need is the one you were writing to.
Here is an example using the file() function which reads each line of a file into an array.
$file = '/var/apache2/htdocs/loginS/host.txt';
$content = file($file);
$save = fopen('./out.csv', 'w+');
foreach($content as $line) {
$line = rtrim($line, "\r\n"); // remove the newline from $line
$parts = explode("\t", $line);
$lineCsv = implode('|', $parts); // or ',' ?
fwrite($save, $lineCsv . "\n"); // write output to file
}
fclose($save);