I am trying to get the API data from a cache file if there already was the same request recently. Everything works fine but I am just not able to get the content from the cache file even tho it is there. I can't find an error. I hope u can help me.
$url = /* API URL */;
function getJson($url) {
$cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url) . '.json';
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = filemtime($cacheFile);
if ($cacheTime > strtotime('-60 minutes')) {
$json = fread($fh);
return $json;
}
fclose($fh);
unlink($cacheFile);
}
$json = file_get_contents($url);
$fh = fopen($cacheFile, 'w');
fwrite($fh, $json);
fclose($fh);
return $json;
}
$datab = getJson($url);
$data = json_decode($datab, true);
print_r($data);
Il you dont check for your error log or display errors on screen you gonna have a bad time finding its.
Here you have a $cacheFile which should be a $cachePath, so prefix with './' or better DIR
Then you call fread without second parameter, and so on...check your error log, enable all errors.
You must specify the length that needs to be read in fread.
Use:
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = filemtime($cacheFile);
if ($cacheTime > strtotime('-60 minutes')) {
$json = fread($fh,filesize($cacheFile));
fclose($fh); //Remember to release resources
return $json;
}
fclose($fh);
unlink($cacheFile);
}
Alternatively use file_get_contents($cacheFile) to get the whole file without the need for an fopen first.
Related
I need to transfer files of any type or size over HTTP/GET in ~1k chunks. The resulting file hash needs to match the source file. This needs to be done in native PHP without any special tools. I have a basic strategy but I'm getting odd results. This proof of concept just copies the file locally.
CODE
<?php
$input="/home/lm1/Music/Ellise - Feeling Something Bad.mp3";
$a=pathinfo($input);
$output=$a["basename"];
echo "\n> ".md5_file($input);
$fp=fopen($input,'rb');
if ($fp) {
while(!feof($fp)) {
$buffer=base64_encode(fread($fp,1024));
// echo "\n\n".md5($buffer);
write($output,$buffer);
}
fclose($fp);
echo "\n> ".md5_file($output);
echo "\n";
}
function write($file,$buffer) {
// echo "\n".md5($buffer);
$fp = fopen($file, 'ab');
fwrite($fp, base64_decode($buffer));
fclose($fp);
}
?>
OUTPUT
> d31e102b1cae9c73bbf5a12615a8ea36
> 9f03f6c88ed61c07cb534922d6d31864
Thanks in advance.
fread already advances the file pointer position, so there's no need to keep track of it. Same with frwite, so consecutive calls automatically append to the given file. Thus, you could simplify your approach to (code adapted from this answer on how to efficiently write a large input stream to a file):
$src = "a.test";
$dest = "b.test";
$fp_src = fopen($src, 'rb');
if ($fp_src) {
$fp_dest = fopen($dest, 'wb');
$buffer_size = 1024;
while(!feof($fp_src)) {
fwrite($fp_dest, fread($fp_src, $buffer_size));
}
fclose($fp_src);
fclose($fp_dest);
echo md5_file($src)."\n"; // 88e4af2f85080a280e7f00e50d96b7f7
echo md5_file($dest)."\n"; // 88e4af2f85080a280e7f00e50d96b7f7
}
If you want to keep both processes separated, you'd do:
$src = "a.test";
$dest = "b.test";
if (file_exists($dest)) {
unlink($dest); // So we don't append to an existing file
}
$fp = fopen($src,'rb');
if ($fp) {
while(!feof($fp)){
$buffer = base64_encode(fread($fp, 1024));
write($dest, $buffer);
}
fclose($fp);
}
function write($file, $buffer) {
$fp = fopen($file, 'ab');
fwrite($fp, base64_decode($buffer));
fclose($fp);
}
echo md5_file($src)."\n"; // 88e4af2f85080a280e7f00e50d96b7f7
echo md5_file($dest)."\n"; // 88e4af2f85080a280e7f00e50d96b7f7
As for how to stream files over HTTP, you might want to have a look at:
Streaming a large file using PHP
As you can see in the code below, I'm trying to use flock to prevent other clients to acess the php (actually multiple users will acess this something like 10 times per second, each one), as I've found searching here... But this is not working. My data.txt is getting blank everytime doing this.
<?php
$fileName = $_GET["room"]."/data.txt";
function replaceLine($data){
if (stristr($data, $_GET["player"])){
return $_GET["player"]." ".$_GET["data"]."\n";
}
return $data;
}
$file = fopen($fileName,"r");
if (flock($file, LOCK_EX)){
//ftruncate($file, 0);
///--------------
$data = file($fileName);
$data = array_map("replaceLine", $data);
file_put_contents($fileName, implode('', $data));
echo fread($file, filesize($fileName)+1);
///--------------
fflush($file);
flock($file, LOCK_UN);
} else {
echo "wait";
}
fclose($file);
?>
This is the original code (that I was trying to modify to prevent making the file empty): (It works as I want, but have this file problem...)
<?php
$fileName = $_GET["room"]."/data.txt";
function replaceLine($data){
if (stristr($data, $_GET["player"])){
return $_GET["player"]." ".$_GET["data"]."\n";
}
return $data;
}
$data = file($fileName);
$data = array_map("replaceLine", $data);
file_put_contents($fileName, implode('', $data));
$file = fopen($fileName,"r");
echo fread($file, filesize($fileName)+1);
fclose($file);
?>
Sorry for asking this newbie question, but I have not idea how to fix this and I'm searching and trying different things for weeks! Thanks!
You are opening the file for read only and then you are attempting to write to that same file. Try setting the fopen parameter to read/write.
$file = fopen($fileName,"r+");
I would also use fwrite() instead of file_put_contents() since you already have the file pointer and opening it again will likely be denied by the lock.
This is the code I've figured out.
<?php
$username = $_POST['username'];
$email = $_POST['email'];
$json = '{"username":"'.$username.'",'.'"email":"'.$email.'"}';
$file = fopen('token_data.json','w+');
fwrite($file, $json);
fclose($file);
?>
But this is absolutely not the right way.
If your $_POST array has all of the data you need you can encode it as JSON and write to a file:
<?php
$json = json_encode($_POST);
$file = fopen('token_data.json','w+');
fwrite($file, $json);
fclose($file);
?>
If you want to append to the file you will need to read the file into an array first, add the newer parts of the array then encode it again before writing back to the file just like my friend #Rizier123 describes.
Okay, I found a more efficient way to do this.
Original Answer
// read the file if present
$handle = #fopen($filename, 'r+');
// create the file if needed
if ($handle === null)
{
$handle = fopen($filename, 'w+');
}
if ($handle)
{
// seek to the end
fseek($handle, 0, SEEK_END);
// are we at the end of is the file empty
if (ftell($handle) > 0)
{
// move back a byte
fseek($handle, -1, SEEK_END);
// add the trailing comma
fwrite($handle, ',', 1);
// add the new json string
fwrite($handle, json_encode($event) . ']');
}
else
{
// write the first event inside an array
fwrite($handle, json_encode(array($event)));
}
// close the handle on the file
fclose($handle);
}
Without decoding the whole JSON file into the arrays.
I am using weatherundeground.com to get weather data but I always reach the API calls limit so I was thinking about caching the json response every 60 minutes.
This is my simple php script
<?php
$json_string = file_get_contents("http://api.wunderground.com/api/apikey/conditions/forecast/lang:IT/q/CITY1.json");
$parsed_json = json_decode($json_string);
$city1 = $parsed_json->{'current_observation'}->{'display_location'}->{'city'};
I searched and found this answer: Caching JSON output in PHP
I tried to merge them like this:
$url = "http://api.wunderground.com/api/apikey/conditions/forecast/lang:IT/q/SW/Acquarossa.json";
function getJson($url) {
// cache files are created like cache/abcdef123456...
$cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url) . '.json';
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = trim(fgets($fh));
// if data was cached recently, return cached data
if ($cacheTime > strtotime('-60 minutes')) {
return fread($fh);
}
// else delete cache file
fclose($fh);
unlink($cacheFile);
}
$json = file_get_contents($url);
$fh = fopen($cacheFile, 'w');
fwrite($fh, time() . "\n");
fwrite($fh, $json);
fclose($fh);
return $json;
}
$json_string = getJson($url);
$parsed_json = json_decode($json_string);
$city1 = $parsed_json->{'current_observation'}->{'display_location'}->{'city'};
I have been able to set it up and now it gets the first "round" of data, but the 2nd one and all the following, give me an error:
Warning: fread() expects exactly 2 parameters, 1 given in /home/*****/public_html/*****/acquarossa.php on line 27.
And if I put the cached json on any json validator, it says that it isn't a valid json.
( this is the cached file: http://spinnaker.url.ph/meteo/cache/1f58bbab7bf88f3f8561b769475cb7c1.json )
What can I do?
P.S.:I already CHMOD 777 the directory
Actually, the warning is pretty clear about whats going wrong. fread() expects 2 parameters but you're only passing on one in line 27: return fread($fh);
Reading the manual for fread I guess you can fix this by changing
return fread($fh);
to
return fread($fh, filesize($chacheFile));
I want to create new .txt files but as this code is always returning false, the ajax success function is not executed.
the all code is:
<?php
$nome = $_POST["nome"];
$datanasc = $_POST["datanasc"];
$genero = $_POST["genero"];
$nat = $_POST["nat"];
$morada = $_POST["morada"];
$mail = $_POST["mail"];
$existe = false;
$myFile = "Users.txt";
$myFile1 = "Current_User.txt";
$fh = fopen($myFile, "r")or die("can't open file");
while (($line_of_text = fgets($fh))) {
$Data = explode(';', $line_of_text);
if($nome == $Data[0] && $datanasc == $Data[1] && $genero == $Data[2] && $nat == $Data[3] && $morada == $Data[4] && $mail == $Data[5]){
$existe = true;
break;
}
}
fclose($fh);
if($existe == true){
$arrayToJs["existe"] = $existe;
}
else{
$arrayToJs["existe"] = $existe;
$fh = fopen($myFile, "a")or die("can't open file");
$stringData = $nome.";".$datanasc.";".$genero.";".$nat.";".$morada.";".$mail.";"."\n";
//print_r($stringData);
fwrite($fh, $stringData);
fclose($fh);
$fh1 = fopen($myFile1, "w")or die("can't open file");
fwrite($fh1, $stringData);
fclose($fh1);
there is the problem in the code cause is returning false and the ajax success function is not executed. . .
if((!file_exists($nome.'_Favoritos.txt')) && (!file_exists($nome.'_Cesto.txt'))) {
$ffav = $nome.'_Favoritos.txt';
$handle = fopen($ffav, 'w') or die('Cannot open file: ');
fclose($ffav);
$fcart = $nome.'_Cesto.txt';
$handle = fopen($fcart, 'w') or die('Cannot open file: ');
fclose($fcart);
}
}
echo json_encode($arrayToJs);
?>
Thank you all guys!
Use the file pointer ($handle) you created with fclose:
if((!file_exists($nome.'_Favoritos.txt')) && (!file_exists($nome.'_Cesto.txt'))) {
$ffav = $nome.'_Favoritos.txt';
$handle = fopen($ffav, 'w') or die('Cannot open file: ');
fclose($handle);
$fcart = $nome.'_Cesto.txt';
$handle = fopen($fcart, 'w') or die('Cannot open file: ');
fclose($handle);
}
Otherwise your file will always return PHP error when those files do not exist
Whether or not your AJAX success function gets called has nothing to do with a PHP code's "return value."
Assuming you're using jQuery or one of the other JavaScript frameworks, it has to do with the HTTP response code. Presumably, you're probably encountering a PHP error which is resulting in a 500 response back to the browser. This would end you up in the error handler instead of the success handler.
Have you tried using something like the network inspector in Chrome (or the Net tab in Firebug) to investigate the actual HTTP response?
This code is not returning any value please pass value (true/false) after file created to ajax response.
If you pass a relative path to file_exists, it will return false unless the path happens to be relative to the current PHP directory.