Why sometimes can't get content using file_get_contents()? - php

The code is simple:
<?php
function getStringFromUrl($url){
$fResource = fopen($url, 'r');
do {
$data = fread($fResource, 8192);
if (strlen($data) == 0) {
break;
}
$contents .= $data;
} while(true);
fclose ($fResource);
$contents = mb_convert_encoding($contents,'utf-8','gbk');
return $contents;
}
echo getStringFromUrl(urlencode('http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=text&ip=119.97.23.59'));
echo file_get_contents('http://blog.sina.com.cn/rss/1400122351.xml');
Sometimes I can get content, sometimes not. I can't figure out why.
(EDIT:the error msg is :[function.fopen]: failed to open stream and [function.file-get-contents]: failed to open stream)
Of course the 2 URL above are available.
I have also set the allow_url_fopen = On in php.ini.

First of all - you don't need to urlencode full url! Only GET parameters:
echo file_get_contents('http://int.dpool.sina.com.cn/iplookup/iplookup.php?'.http_build_query(array(
'format' => 'text',
'ip' => '119.97.23.59'
)));
Second thing you should share with is error message (if any)

Related

How do I download and save images from url

I have this URL
'http://2.bp.blogspot.com/-LBbpkomI7JQ/VnLmeFZANgI/AAAAAAAAWhc/MsdZjtxN0HQ/s0-Ic42/RCO001.jpg '
I tried to do some search and did this
$file = fopen("C:\Users\Alex\Desktop\script.txt", "r");
$links = array();
while (!feof($file)) {
$links[] = fgets($file);
}
fclose($file);
foreach($links as $num => $link)
{
echo "'".$link."'";
save_image("'".$link."'","'".$num."'".".jpg");
}
var_dump($links);
function save_image($inPath,$outPath)
{ //Download images from remote server
$in= fopen($inPath, "rb");
$out= fopen($outPath, "wb");
while ($chunk = fread($in,8192))
{
fwrite($out, $chunk, 8192);
}
fclose($in);
fclose($out);
}
All urls are in my script.txt file so I am storing them in an array then calling each url one by one but it says
failed to open stream: Invalid argument
Anything missing or wrong?
You could try this implementation (works great for me):
<?php
$links = explode("\n", file_get_contents("C:\Users\Alex\Desktop\script.txt"));
foreach($links as $num => $link)
{
echo $link . "\n";
save_image($link, $num.".jpg");
}
function save_image($inPath, $outPath)
{
$inPath = trim($inPath);
if ($inPath != "") {
file_put_contents($outPath, file_get_contents($inPath));
}
}
assuming your script.txt looks like this
http://2.bp.blogspot.com/-LBbpkomI7JQ/VnLmeFZANgI/AAAAAAAAWhc/MsdZjtxN0HQ/s0-Ic42/RCO001.jpg
In this line:
$file = fopen("C:\Users\Alex\Desktop\script.txt", "r");
Your backslashes might be converted into special chars by PHP, this could cause a problem, so
look at this topic:
failed to open stream: Invalid argument
Second thing:
It might be a problem with fopen configuration
Edit your php.ini and set:
allow_url_fopen = On
You can check this value (it's probably false):
var_dump(ini_get('allow_url_fopen'));
You'll need to speak to your web host, or try another method. Mabye CURL is enabled?
You should also check your display_errors and error_reporting values. PHP should have complained loudly about being unable to open the URL.

Issue on Reading .txt inside a Zipped File by PHP [duplicate]

I need to read the content of a single file, "test.txt", inside of a zip file. The whole zip file is a very large file (2gb) and contains a lot of files (10,000,000), and as such extracting the whole thing is not a viable solution for me. How can I read a single file?
Try using the zip:// wrapper:
$handle = fopen('zip://test.zip#test.txt', 'r');
$result = '';
while (!feof($handle)) {
$result .= fread($handle, 8192);
}
fclose($handle);
echo $result;
You can use file_get_contents too:
$result = file_get_contents('zip://test.zip#test.txt');
echo $result;
Please note #Rocket-Hazmat fopen solution may cause an infinite loop if a zip file is protected with a password, since fopen will fail and feof fails to return true.
You may want to change it to
$handle = fopen('zip://file.zip#file.txt', 'r');
$result = '';
if ($handle) {
while (!feof($handle)) {
$result .= fread($handle, 8192);
}
fclose($handle);
}
echo $result;
This solves the infinite loop issue, but if your zip file is protected with a password then you may see something like
Warning: file_get_contents(zip://file.zip#file.txt): failed to open
stream: operation failed
There's a solution however
As of PHP 7.2 support for encrypted archives was added.
So you can do it this way for both file_get_contents and fopen
$options = [
'zip' => [
'password' => '1234'
]
];
$context = stream_context_create($options);
echo file_get_contents('zip://file.zip#file.txt', false, $context);
A better solution however to check if a file exists or not before reading it without worrying about encrypted archives is using ZipArchive
$zip = new ZipArchive;
if ($zip->open('file.zip') !== TRUE) {
exit('failed');
}
if ($zip->locateName('file.txt') !== false) {
echo 'File exists';
} else {
echo 'File does not exist';
}
This will work (no need to know the password)
Note: To locate a folder using locateName method you need to pass it like folder/ with a
forward slash at the end.

Open content.xml in a odt-file directly via php [duplicate]

I need to read the content of a single file, "test.txt", inside of a zip file. The whole zip file is a very large file (2gb) and contains a lot of files (10,000,000), and as such extracting the whole thing is not a viable solution for me. How can I read a single file?
Try using the zip:// wrapper:
$handle = fopen('zip://test.zip#test.txt', 'r');
$result = '';
while (!feof($handle)) {
$result .= fread($handle, 8192);
}
fclose($handle);
echo $result;
You can use file_get_contents too:
$result = file_get_contents('zip://test.zip#test.txt');
echo $result;
Please note #Rocket-Hazmat fopen solution may cause an infinite loop if a zip file is protected with a password, since fopen will fail and feof fails to return true.
You may want to change it to
$handle = fopen('zip://file.zip#file.txt', 'r');
$result = '';
if ($handle) {
while (!feof($handle)) {
$result .= fread($handle, 8192);
}
fclose($handle);
}
echo $result;
This solves the infinite loop issue, but if your zip file is protected with a password then you may see something like
Warning: file_get_contents(zip://file.zip#file.txt): failed to open
stream: operation failed
There's a solution however
As of PHP 7.2 support for encrypted archives was added.
So you can do it this way for both file_get_contents and fopen
$options = [
'zip' => [
'password' => '1234'
]
];
$context = stream_context_create($options);
echo file_get_contents('zip://file.zip#file.txt', false, $context);
A better solution however to check if a file exists or not before reading it without worrying about encrypted archives is using ZipArchive
$zip = new ZipArchive;
if ($zip->open('file.zip') !== TRUE) {
exit('failed');
}
if ($zip->locateName('file.txt') !== false) {
echo 'File exists';
} else {
echo 'File does not exist';
}
This will work (no need to know the password)
Note: To locate a folder using locateName method you need to pass it like folder/ with a
forward slash at the end.

PHP: fopen error handling

I do fetch a file with
$fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb");
$str = stream_get_contents($fp);
fclose($fp);
and then the method gives it back as image. But when fopen() fails, because the file did not exists, it throws an error:
[{"message":"Warning: fopen(uploads\/Team\/img\/1.png): failed to open stream: No such file or directory in C:\...
This is coming back as json, obviously.
The Question is now: How can i catch the error and prevent the method from throwing this error directly to the client?
You should first test the existence of a file by file_exists().
try
{
$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( !file_exists($fileName) ) {
throw new Exception('File not found.');
}
$fp = fopen($fileName, "rb");
if ( !$fp ) {
throw new Exception('File open failed.');
}
$str = stream_get_contents($fp);
fclose($fp);
// send success JSON
} catch ( Exception $e ) {
// send error message if you can
}
or simple solution without exceptions:
$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( file_exists($fileName) && ($fp = fopen($fileName, "rb"))!==false ) {
$str = stream_get_contents($fp);
fclose($fp);
// send success JSON
}
else
{
// send error message if you can
}
You can use the file_exists() function before calling fopen().
if(file_exists('uploads/Team/img/'.$team_id.'.png')
{
$fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb");
$str = stream_get_contents($fp);
fclose($fp);
}
[{"message":"Warning: fopen(uploads\/Team\/img\/1.png): failed to open stream: No such file or directory in C:\...
the error is clear: you've put the wrong directory, you can try what you whant but it'll not work. you can make it work with this:
take your file and put it in the same folder of your php file
(you'll be able to move it after don't worry, it's about your error)
or on a folder "higher" of your script (just not outside of your www
folder)
change the fopen to ('./$team_id.'png',"rb");
rerun your script file
don't forget this : you can't access a file that is'nt in your "www" folder
(he doesn't found your file because he give you her name: the name come from the $team_id variable)
Generically - This is probably the best way to do file-io in php (as mentioned by #Cendak here)
$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( file_exists($fileName) && ($fp = fopen($fileName, "rb"))!==false ){
$str = stream_get_contents($fp);
fclose($fp);
// send success JSON
}else{
// send an error message if you can
}
But it does not work with PHP 7.3, these modifications do,
if(file_exists($filename) && ($fp = fopen($filename,"r") !== false)){
$fp = fopen($filename,"r");
$filedata = fread($fp,filesize($filename));
fclose($fp);
}else{
$filedata = "default-string";
}

Script to download and extract zip files returns errors

Hey everyone, I have written a script that downloads a zip file from a remote source, and then is supposed to extract the zip file to a directory. Below is the script:
<?php
$url = "http://example.com/some_file.zip";
download($url,'file.zip');
function download($url,$file_name = NULL){
if($file_name == NULL){ $file_name = basename($url);}
$url_stuff = parse_url($url);
$port = isset($url_stuff['port']) ? $url_stuff['port'] : 80;
$fp = fsockopen($url_stuff['host'], $port);
if(!$fp){ return false;}
$query = 'GET ' . $url_stuff['path'] . " HTTP/1.0\n";
$query .= 'Host: ' . $url_stuff['host'];
$query .= "\n\n";
fwrite($fp, $query);
while ($tmp = fread($fp, 8192)) {
$buffer .= $tmp;
}
preg_match('/Content-Length: ([0-9]+)/', $buffer, $parts);
$file_binary = substr($buffer, - $parts[1]);
if($file_name == NULL){
$temp = explode(".",$url);
$file_name = $temp[count($temp)-1];
}
if(!file_exists("packages")){ mkdir("packages", 0755);}
$file_open = fopen("packages/" . $file_name,'w');
if(!$file_open){ return false;}
fwrite($file_open,$file_binary);
$zip = zip_open(realpath("packages")."/".$file_name);
if ($zip) {
while ($zip_entry = zip_read($zip)) {
$fp = fopen("some_dir/".zip_entry_name($zip_entry), "w");
if(zip_entry_open($zip, $zip_entry, "r")) {
$buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
fwrite($fp,"$buf");
zip_entry_close($zip_entry);
fclose($fp);
}
}
zip_close($zip);
}
fclose($file_open);
return true;
}
?>
The issue that I have is that while the downloading of the remote file works flawlessly, I can't seem to extract it. The zip_read() and zip_close() return errors saying that it "expects parameter 1 to be resource, integer given...", which I have found means that the zip_open() was unable to extract and is returning an error code, which I have found to be "19" meaning "Zip File Function error: Not a zip archive". However, I know the file I am downloading is, in fact, a zip file. Can anyone explain this odd behavior and provide a fix? It would be much appreciated!
Quoting php.net: "zip_open() ... Returns a resource handle for later use with zip_read() and zip_close() or returns the number of error if filename does not exist or in case of other error."
This means you cannot test if ($zip) like that. Try
if ( is_resource($zip) ) {
// stuff
} else {
print "Zip_open() returned error $zip\n";
}
edit: Apart from that, you need to cut the response in 2 parts properly. You are relying heavily on the Content-Length parameter. You don't check if the preg_match actually matched. A lot of things can go wrong and you should check those things. Try splitting the content on the first empty line (explode on \r\n\r\n or something like that)
Besides the fread() loop should check for feof(), since you would stop reading now if for some reason you would encounter an empty read. Copy&paste from php.net:
while (!feof($handle)) {
$contents .= fread($handle, 8192);
}
But we can go on and on here. Three main points have to be made:
read the fantastic manual (php.net)
check return values
don't assume you know things you don't
those are related: you must lookup the manual to see what return values you might encounter.

Categories