Related
I'm writing a tiny webpage whose purpose is to frame a few other pages, simply to consolidate them into a single browser window for ease of viewing. A few of the pages I'm trying to frame forbid being framed and throw a "Refused to display document because display forbidden by X-Frame-Options." error in Chrome. I understand that this is a security limitation (for good reason), and don't have access to change it.
Is there any alternative framing or non-framing method to display pages within a single window that won't get tripped up by the X-Frame-Options header?
I had a similar issue, where I was trying to display content from our own site in an iframe (as a lightbox-style dialog with Colorbox), and where we had an server-wide "X-Frame-Options SAMEORIGIN" header on the source server preventing it from loading on our test server.
This doesn't seem to be documented anywhere, but if you can edit the pages you're trying to iframe (eg., they're your own pages), simply sending another X-Frame-Options header with any string at all disables the SAMEORIGIN or DENY commands.
eg. for PHP, putting
<?php
header('X-Frame-Options: GOFORIT');
?>
at the top of your page will make browsers combine the two, which results in a header of
X-Frame-Options SAMEORIGIN, GOFORIT
...and allows you to load the page in an iframe. This seems to work when the initial SAMEORIGIN command was set at a server level, and you'd like to override it on a page-by-page case.
All the best!
If you are getting this error for a YouTube video, rather than using the full url use the embed url from the share options. It will look like http://www.youtube.com/embed/eCfDxZxTBW4
You may also replace watch?v= with embed/ so http://www.youtube.com/watch?v=eCfDxZxTBW4 becomes http://www.youtube.com/embed/eCfDxZxTBW4
If you are getting this error while trying to embed a Google Map in an iframe, you need to add &output=embed to the source link.
UPDATE 2019: You can bypass X-Frame-Options in an <iframe> using just client-side JavaScript and my X-Frame-Bypass Web Component. Here is a demo: Hacker News in an X-Frame-Bypass. (Tested in Chrome & Firefox.)
There is a plugin for Chrome, that drops that header entry (for personal use only):
https://chrome.google.com/webstore/detail/ignore-x-frame-headers/gleekbfjekiniecknbkamfmkohkpodhe/reviews
Adding a
target='_top'
to my link in the facebook tab fixed the issue for me...
If you're getting this error trying to embed Vimeo content, change the src of the iframe, from: https://vimeo.com/63534746 to: http://player.vimeo.com/video/63534746
I had same issue when I tried embed moodle 2 in iframe, solution is Site administration ► Security ► HTTP security and check Allow frame embedding
Solution for loading an external website into an iFrame even tough the x-frame option is set to deny on the external website.
If you want to load a other website into an iFrame and you get the Display forbidden by X-Frame-Options” error then you can actually overcome this by creating a server side proxy script.
The src attribute of the iFrame could have an url looking like this: /proxy.php?url=https://www.example.com/page&key=somekey
Then proxy.php would look something like:
if (isValidRequest()) {
echo file_get_contents($_GET['url']);
}
function isValidRequest() {
return $_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['key']) &&
$_GET['key'] === 'somekey';
}
This by passes the block, because it is just a GET request that might as wel have been a ordinary browser page visit.
Be aware: You might want to improve the security in this script. Because hackers could start loading in webpages via your proxy script.
This is the solution guys!!
FB.Event.subscribe('edge.create', function(response) {
window.top.location.href = 'url';
});
The only thing that worked for facebook apps!
I tried nearly all suggestions. However, the only thing that really solved the issue was:
Create an .htaccess in the same folder where your PHP file lies.
Add this line to the htaccess:
Header always unset X-Frame-Options
Embedding the PHP by an iframe from another domain should work afterwards.
Additionally you could add in the beginning of your PHP file:
header('X-Frame-Options: ALLOW');
Which was, however, not necessary in my case.
It appears that X-Frame-Options Allow-From https://... is depreciated and was replaced (and gets ignored) if you use Content-Security-Policy header instead.
Here is the full reference: https://content-security-policy.com/
I had the same problem with mediawiki, this was because the server denied embedding the page into an iframe for security reasons.
I solved it writing
$wgEditPageFrameOptions = "SAMEORIGIN";
into the mediawiki php config file.
Hope it helps.
Not mentioned but can help in some instances:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status === 200) {
var doc = iframe.contentWindow.document;
doc.open();
doc.write(xhr.responseText);
doc.close();
}
}
xhr.open('GET', url, true);
xhr.send(null);
FWIW:
We had a situation where we needed to kill our iFrame when this "breaker" code showed up. So, I used the PHP function get_headers($url); to check out the remote URL before showing it in an iFrame. For better performance, I cached the results to a file so I was not making a HTTP connection each time.
I was using Tomcat 8.0.30, none of the suggestions worked for me. As we are looking to update the X-Frame-Options and set it to ALLOW, here is how I configured to allow embed iframes:
Navigate to Tomcat conf directory, edit the web.xml file
Add the below filter:
<filter>
<filter-name>httpHeaderSecurity</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>antiClickJackingEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>antiClickJackingOption</param-name>
<param-value>ALLOW-FROM</param-value>
</init-param>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>httpHeaderSecurity</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Restart Tomcat service
Access the resources using an iFrame.
The only question that has a bunch of answers. WElcome to the guide i wish i had when i was scrambling for this to make it work at 10:30 at night on the deadline day... FB does some weird things with canvas apps, and well, you've been warned. If youa re still here and you have a Rails app that will appear behind a Facebook Canvas, then you will need:
Gemfile:
gem "rack-facebook-signed-request", :git => 'git://github.com/cmer/rack-facebook-signed-request.git'
config/facebook.yml
facebook:
key: "123123123123"
secret: "123123123123123123secret12312"
config/application.rb
config.middleware.use Rack::Facebook::SignedRequest, app_id: "123123123123", secret: "123123123123123123secret12312", inject_facebook: false
config/initializers/omniauth.rb
OmniAuth.config.logger = Rails.logger
SERVICES = YAML.load(File.open("#{::Rails.root}/config/oauth.yml").read)
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, SERVICES['facebook']['key'], SERVICES['facebook']['secret'], iframe: true
end
application_controller.rb
before_filter :add_xframe
def add_xframe
headers['X-Frame-Options'] = 'GOFORIT'
end
You need a controller to call from Facebook's canvas settings, i used /canvas/ and made the route go the main SiteController for this app:
class SiteController < ApplicationController
def index
#user = User.new
end
def canvas
redirect_to '/auth/failure' if request.params['error'] == 'access_denied'
url = params['code'] ? "/auth/facebook?signed_request=#{params['signed_request']}&state=canvas" : "/login"
redirect_to url
end
def login
end
end
login.html.erb
<% content_for :javascript do %>
var oauth_url = 'https://www.facebook.com/dialog/oauth/';
oauth_url += '?client_id=471466299609256';
oauth_url += '&redirect_uri=' + encodeURIComponent('https://apps.facebook.com/wellbeingtracker/');
oauth_url += '&scope=email,status_update,publish_stream';
console.log(oauth_url);
top.location.href = oauth_url;
<% end %>
Sources
The config i think came from omniauth's example.
The gem file (which is key!!!) came from: slideshare things i learned...
This stack question had the whole Xframe angle, so you'll get a blank space, if
you don't put this header in the app controller.
And my man #rafmagana wrote this heroku guide, which now you can adopt for rails with this answer and the shoulders of giants in which you walk with.
The only real answer, if you don't control the headers on your source you want in your iframe, is to proxy it. Have a server act as a client, receive the source, strip the problematic headers, add CORS if needed, and then ping your own server.
There is one other answer explaining how to write such a proxy. It isn't difficult, but I was sure someone had to have done this before. It was just difficult to find it, for some reason.
I finally did find some sources:
https://github.com/Rob--W/cors-anywhere/#documentation
^ preferred. If you need rare usage, I think you can just use his heroku app. Otherwise, it's code to run it yourself on your own server. Note sure what the limits are.
whateverorigin.org
^ second choice, but quite old. supposedly newer choice in python: https://github.com/Eiledon/alloworigin
then there's the third choice:
http://anyorigin.com/
Which seems to allow a little free usage, but will put you on a public shame list if you don't pay and use some unspecified amount, which you can only be removed from if you pay the fee...
<form target="_parent" ... />
Using Kevin Vella's idea, I tried using the above on the form element made by PayPal's button generator. Worked for me so that Paypal does not open in a new browser window/tab.
Update
Here's an example:
Generating a button as of today (01-19-2021), PayPal automatically includes target="_top" on the form element, but if that doesn't work for your context, try a different target value. I suggest _parent -- at least that worked when I was using this PayPal button.
See Form Target Values for more info.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_parent">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="name#email.com">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="button_subtype" value="services">
<input type="hidden" name="no_note" value="0">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynowCC_LG.gif:NonHostedGuest">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
I'm not sure how relevant it is, but I built a work-around to this. On my site, I wanted to display link in a modal window that contained an iframe which loads the URL.
What I did is, I linked the click event of the link to this javascript function. All this does is make a request to a PHP file that checks the URL headers for X-FRAME-Options before deciding whether to load the URL within the modal window or to redirect.
Here's the function:
function opentheater(link, title){
$.get( "url_origin_helper.php?url="+encodeURIComponent(link), function( data ) {
if(data == "ya"){
$(".modal-title").html("<h3 style='color:480060;'>"+title+" <small>"+link+"</small></h3>");
$("#linkcontent").attr("src", link);
$("#myModal").modal("show");
}
else{
window.location.href = link;
//alert(data);
}
});
}
Here's the PHP file code that checks for it:
<?php
$url = rawurldecode($_REQUEST['url']);
$header = get_headers($url, 1);
if(array_key_exists("X-Frame-Options", $header)){
echo "nein";
}
else{
echo "ya";
}
?>
Hope this helps.
I came across this issue when running a wordpress web site. I tried all sorts of things to fix it and wasn't sure how, ultimately the issue was because I was using DNS forwarding with masking, and the links to external sites were not being addressed properly. i.e. my site was hosted at http://123.456.789/index.html but was masked to run at http://somewebSite.com/index.html. When i entered http://123.456.789/index.html in the browser clicking on those same links resulted in no X-frame-origins issues in the JS console, but running http://somewebSite.com/index.html did. In order to properly mask you must add your host's DNS name servers to your domain service, i.e. godaddy.com should have name servers of example, ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com, if you were using digitalocean.com as your hosting service.
It's surprising that no one here has ever mentioned Apache server's settings (*.conf files) or .htaccess file itself as being a cause of this error. Search through your .htaccess or Apache configuration files, making sure that you don't have the following set to DENY:
Header always set X-Frame-Options DENY
Changing it to SAMEORIGIN, makes things work as expected:
Header always set X-Frame-Options SAMEORIGIN
i had this problem, and resolved it editing httd.conf
<IfModule headers_module>
<IfVersion >= 2.4.7 >
Header always setifempty X-Frame-Options GOFORIT
</IfVersion>
<IfVersion < 2.4.7 >
Header always merge X-Frame-Options GOFORIT
</IfVersion>
</IfModule>
i changed SAMEORIGIN to GOFORIT
and restarted server
Site owners use the X-Frame-Options response header so that their website cannot be opened in an Iframe. This helps to secure the users against clickjacking attack
There are a couple of approaches that you can try if you want to disable X-Frame-Options on your own machine.
Configuration at Server-Side
If you own the server or can work with the site owner then you can ask to set up a configuration to not send the Iframe buster response headers based on certain conditions. Conditions could be an additional request header or a parameter in the URL.
For example - The site owner can add an additional code to not send Iframe buster headers when the site is opened with ?in_debug_mode=true query param.
Use Browser extension like Requestly to remove response headers
You can use any browser extension like Requestly which allows you to modify the request & response headers. Here's a Requestly blog that explains how to embed sites in Iframe by bypassing Iframe buster headers.
Configure a Pass-through Proxy and remove headers from it
If you need to bypass Iframe buster headers for multiple folks, then you can also configure a pass-through proxy that just removes the frame buster response headers and return back the response. This is however a lot complicated to write, set up. There are some other challenges like authentication etc with the sites opened in Iframe through a proxy but this approach can work for simple sites pretty well.
PS - I have built both solutions and have first-hand experience with both.
Edit .htaccess if you want to remove X-Frame-Options from an entire directory.
And add the line: Header always unset X-Frame-Options
[contents from: Overcoming "Display forbidden by X-Frame-Options"
Use this line given below instead of header() function.
echo "<script>window.top.location = 'https://apps.facebook.com/yourappnamespace/';</script>";
Try this thing, i dont think anyone suggested this in the Topic, this will resolve like 70% of your issue, for some other pages, you have to scrap, i have the full solution but not for public,
ADD below to your iframe
sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
I am offering a pdf document in the form of a download from my website via a landing page.
I want to hide the URL/link that displays in the address bar and when i hover over the download button on the web page so that the link cant be shared.
What is the best way to do this? Please explain carefully.
Thanks
Ok, you cannot do that with plain HTML. You can use all kind of tricks but they can be a problem to the user experience, you are to use a server side language.
What you can do is create a php page, name it the way you want (let's say download.php), and link to that one. The page should be something like this:
// Path to the file
$path = '/home/folder/yourfile.pdf';
// This is based on file type of $path, but not always needed
$mm_type = "application/octet-stream";
//Set headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");
// Outputs the content of the file
readfile($path);
exit();
This way you just link to your download.php page and it downloads/opens the PDF, like so:
Download
Edited based on BenjaminC suggestions
The other chance you have is to connect this to a database. The database has a table named downloads_table and inside you have 2 fields:
secret: char(32)
downloaded: int(1) dafault 0
Then you create an md5 string
$secret = md5(rand(1000, 9999999));
Place it inside the secret field, create the link:
Download
The user receives/sees a link, when pressed you are to edit the first line of the above code to check in the db if downloaded field = to 0 than procede to download, otherwise the person sees an error page.
This is so that it can be downloaded only once.
(Edit)
If in the future, this gets useful for anyone, the functionality can be seen in this fiddle: https://jsfiddle.net/aznjr87g/
It downloads 2.1.3 jquery.min.js from google.
(Edit end)
This can be achieved using Html5 's Download attribute.
Download PDF
If you hover your mouse over that, it simply shows yoursite.com/#
Place this somewhere in the body of the webpage:
And place this somewhere in the webpage:
<script>
function download() {
document.getElementById("download").src = "/path/to/download";
}
<script>
Then, on the element of the button (In the example of a div) do this in the tag:
<div onclick="download()"> </div>
However if it's a link you will want to do:
An element needs a href to work properly.
I have a file that I link to from my website like
<a href="http://example.com/myfile.txt>View!</a>
However, this file changes very frequently and when the link is clicked, the browser loads the cached version of the file, not the actual file.
Is there a way so that clicking on that link will bypass the cache for that page?
Something nice like <a bypassCache href=""> would be wishful thinking.
Something nice like would be wishful thinking.
Indeed, there is something you can do from within the link: Add a random GET parameter.
View!
You could use JavaScript (or of course a server-side scripting language like PHP) to do this on a dynamic basis.
However, the far superior way would be to configure the text file's caching headers correctly in the first place on server side. Stealing the header info from Best way to disable client caching, a .htaccess file like this should work:
<Files myfile.txt>
FileETag None
<IfModule mod_headers.c>
Header unset ETag
Header set Cache-Control "store, no-cache, must-revalidate, post-check=0, pre-check=0"
Header set Pragma "no-cache"
Header set Expires "Sun, 19 Nov 1978 05:00:00 GMT"
</IfModule>
</FilesMatch>
Just put
<meta http-equiv="expires" content="0">
Into the head section of your target page and check again
The best way is to tell apache/(web server) to tell browser not allow caching of that file, if you don't have controll over that server, you could avoid cache by alter the parameters send to it, just add some numbers behind ?, for exemple the time when you created the link, this makes each url diferent, so the browser going to ignore the cache, but all links to the same file, as long as the server ignore the extra parameter. in php:
echo "<a href='http://example.com/myfile.txt?" . time() . "'>View!</a>"
Add a random number after the hyper link, such as View!
Generate a new random number each time the page loads.
You can solve your problem on server level. Set the special expiration date for txt resources (or that particular one) that fit to your requirements.
If you use apache you can read about mod_expiry for apache here
I have a problem where users are reporting that their images aren't being uploaded and the old ones are still there. On closer inspection the new images are there, they just have the same name as the old one. What I do on the upload is that I rename the images for SEO purposes. When they delete an image the old index becomes available and is reused. Therefore it has the same image name.
Is there a way to (i thought maybe there might be a meta tag for this) to tell the browser to not use its cahce?
The better answer is to rename the image to something totally new. I will get working on that but in the mean time is the quick solution while I work on the bigger problem.
Append a query string with an arbitrary unique number (or time, or version number, etc.):
<img src="image.png?80172489074" alt="a cool image" />
This will result in a new request, because of the different URL.
It's tough. You really want images to be cached, but then you don't want to cache them once a new ones available:
Using expires header with a date in the past prevents any caching. Bad
Adding a "cache busting" parameter ?342038402 can fix the problem, but can also prevent the image ever from being cached, which is not what you want. Bad.
Using expires header with a short (lets say 1 hr) expires is better... after an hour the user will see the image, but your web server won't have to serve it every time. Compromise, but what time works? Not really feasible.
The solution? I can think of two good options:
Look into eTags, and your ability to use them. These are designed for this situation. The browser will explicitly ask your server whether the file is up-to-date or not. You can just turn this on in apache if you don't have it aleady.
Create a new URL for each new image (and use a far-future expires header). This is what you are working on.
My favourite PHP solution:
<img src="<?php echo "image.jpg" . "?v=" . filemtime("image.jpg"); ?>" />
every change of file "create" a new version of the file
Append the current datetime to the image src:
<img src="yourImage.png?v=<?php echo Date("Y.m.d.G.i.s")?>" />
You can put http-equiv in <meta> tag which will tell browser not to use cache (or even better -- use it in some defined way), but it is better to configure server to send proper http cache headers. Check out article on caching.
Still, some browsers might not support all of http standard, but I believe it's the way to go.
Another powerfull solution:
<img src="image.png?v=<?php echo filemtime("image.png"); ?>" />
This print the "last-modification-timestamp" on the path.
New version --> Download new image
Same version --> Take cache's one
Go Random. Just use some random number and append it with image filename.
<img src="image.jpg?<?=rand(1,1000000)?>">
you can control the cache behaviour by playing with the HTTP headers.
setting the expires header in past would force browser to not use cached version.
Expires: Sat, 26 Jul 1997 05:00:00 GMT
You can consult the RFC to have more details.
If you look at the data that is exchanged between your browser and the server, you'll see that the browser will send a HTTP HEAD request for the images. The result will contain the modification time (but not the actual image data). Make sure that this time changes if the image changes on the server and the browser should download the image again.
in PHP you can use this trick
<img src="image.png?<?php echo time(); ?>" />
The time() function show the current timestamp. Every page load is different. So this code deceive the browser: it read another path and it "think" that the image is changed since the user has visited the site the last time. And it has to re-download it, instead of use the cache one.
It sounds like the concern is more about the primary user seeing their new image than cache being disabled entirely? If that's the case, you can do the following:
var headers = new Headers()
headers.append('pragma', 'no-cache')
headers.append('cache-control', 'no-cache')
var init = {
method: 'GET',
headers: headers,
mode: 'no-cors',
cache: 'no-cache',
}
fetch(new Request('path/to.file'), init)
If you do this after a new image is uploaded, the browser should see those headers and make a call to the backend, skipping the cache. The new image is now in cache under that URL. The primary user will see the new image, but you still retain all the benefits of caching. Anyone else viewing this image will see updates in a day or so once their cache invalidates.
If the concern was more about making sure all users see the most up to date version, you would want to use one of the other solutions.
In PHP you can send a random number or the current timestamp:
<img src="image.jpg?<?=Date('U')?>">
or
<img src="image.jpg?<?=rand(1,32000)?>">
that was not ok result, I think this is the way to program it correct.
<td><?php echo "<img heigth=90 width=260 border=1 vspace=2 hspace=2 src=".$row['address']."?=".rand(1,999)."/>" ?></td>
I had come up with this issue some times ago. And I was getting data through JSON in AJAX.
So what I did is, I just added a Math.random() Javascript function and It worked like a charm.
The backend I used was a flask.
<img class="card-img-top w-100 d-block" style="padding:30px;height:400px" src="static/img/${data.image}?${Math.random()} ">
I generate some images using a PHP lib.
Sometimes the browser does not load the new generated file.
How can I disable cache just for images created dynamically by me?
Note: I have to use same name for the created images over time.
A common and simple solution to this problem that feels like a hack but is fairly portable is to add a randomly generated query string to each request for the dynamic image.
So, for example -
<img src="image.png" />
Would become
<img src="image.png?dummy=8484744" />
Or
<img src="image.png?dummy=371662" />
From the point of view of the web-server the same file is accessed, but from the point of view of the browser no caching can be performed.
The random number generation can happen either on the server when serving the page (just make sure the page itself isn't cached...), or on the client (using JavaScript).
You will need to verify whether your web-server can cope with this trick.
Browser caching strategies can be controlled by HTTP headers. Remember that they are just a hint, really. Since browsers are terribly inconsistent in this (and any other) field, you'll need several headers to get the desired effect on a range of browsers.
header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");
Solution 1 is not great. It does work, but adding hacky random or timestamped query strings to the end of your image files will make the browser re-download and cache every version of every image, every time a page is loaded, regardless of whether or not the image has changed on the server.
Solution 2 is useless. Adding nocache headers to an image file is not only very difficult to implement, but it's completely impractical because it requires you to predict when it will be needed in advance, the first time you load any image that you think might change at some point in the future.
Enter Etags...
The absolute best way I've found to solve this is to use ETAGS inside a .htaccess file in your images directory. The following tells Apache to send a unique hash to the browser in the image file headers. This hash only ever changes when the image file is modified and this change triggers the browser to reload the image the next time it is requested.
<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>
If you need to do it dynamically in the browser using javascript, here is an example...
<img id=graph alt=""
src="http://www.kitco.com/images/live/gold.gif"
/>
<script language="javascript" type="text/javascript">
var d = new Date();
document.getElementById("graph").src =
"http://www.kitco.com/images/live/gold.gif?ver=" +
d.getTime();
</script>
I checked all the answers and the best one seemed to be (which isn't):
<img src="image.png?cache=none">
at first.
However, if you add cache=none parameter (which is static "none" word), it doesn't effect anything, browser still loads from cache.
Solution to this problem was:
<img src="image.png?nocache=<?php echo time(); ?>">
where you basically add unix timestamp to make the parameter dynamic and no cache, it worked.
However, my problem was a little different:
I was loading on the fly generated php chart image, and controlling the page with $_GET parameters. I wanted the image to be read from cache when the URL GET parameter stays the same, and do not cache when the GET parameters change.
To solve this problem, I needed to hash $_GET but since it is array here is the solution:
$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";
Edit:
Although the above solution works just fine, sometimes you want to serve the cached version UNTIL the file is changed. (with the above solution, it disables the cache for that image completely)
So, to serve cached image from browser UNTIL there is a change in the image file use:
echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";
filemtime() gets file modification time.
I know this topic is old, but it ranks very well in Google. I found out that putting this in your header works well;
<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">
I was just looking for a solution to this, and the answers above didn't work in my case (and I have insufficient reputation to comment on them). It turns out that, at least for my use-case and the browser I was using (Chrome on OSX), the only thing that seemed to prevent caching was:
Cache-Control = 'no-store'
For completeness i'm now using all 3 of 'no-cache, no-store, must-revalidate'
So in my case (serving dynamically generated images out of Flask in Python), I had to do the following to hopefully work in as many browsers as possible...
def make_uncached_response(inFile):
response = make_response(inFile)
response.headers['Pragma-Directive'] = 'no-cache'
response.headers['Cache-Directive'] = 'no-cache'
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response
Changing the image source is the solution. You can indeed do this by adding a timestamp or random number to the image.
Better would be to add a checksum of eg the data the image represents. This enables caching when possible.
Let's add another solution one to the bunch.
Adding a unique string at the end is a perfect solution.
example.jpg?646413154
Following solution extends this method and provides both the caching capability and fetch a new version when the image is updated.
When the image is updated, the filemtime will be changed.
<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>
Now output the image:
<img src="images/example.jpg?<?php echo $filemtime; ?>" >
i had this problem and overcoming like this.
var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';
I've used this to solve my similar problem ... displaying an image counter (from an external provider). It did not refresh always correctly. And after a random parameter was added, all works fine :)
I've appended a date string to ensure refresh at least every minute.
sample code (PHP):
$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";
That results in a src link like:
http://xy.somecounter.com/?id=1234567890&1207241014
If you have a hardcoded image URL, for example: http://example.com/image.jpg you can use php to add headers to your image.
First you will have to make apache process your jpg as php.
See here:
Is it possible to execute PHP with extension file.php.jpg?
Load the image (imagecreatefromjpeg) from file then add the headers from previous answers. Use php function header to add the headers.
Then output the image with the imagejpeg function.
Please notice that it's very insecure to let php process jpg images. Also please be aware I haven't tested this solution so it is up to you to make it work.
Simple, send one header location.
My site, contains one image, and after upload the image, there not change, then I add this code:
<?php header("Location: pagelocalimage.php"); ?>
Work's for me.