Is there any way (server or client side) to force the browser to pull a new version of a file (image) from the server. The image in question is otherwise cached for a long time. I know I can append a random number, for instance, to the URL of the image but this is not acceptable in this situation. I need for the image to be refresh from the exact same URL.
What I'm doing: a YouTube like portal where users upload videos. Each video has a thumbnail which is shown on various pages on the portal. User can, at any time, change the thumbnail (he can select from three generated thumbnails). So when this happens (a new image overwrites the 'original' image), I wan't to refresh the video's thumbnail so that the owner (I don't care if other users see the old thumbnail) will see the new thumbnail no matter where the thumbnail is shown.
I'm afraid this can't be done but I'm asking here just to be sure.
update: I'm using nginx and PHP on the server side
You could use ETAGs on your thumbnails. This would prevent the transmission of the actual thumbnail data if it hasn't changed (i.e. still has the same hash). However, you would still face the clients HTTP requests to check if the ETAG has changed (normly to be answered by HTTP 304.
But combined with a rather short freshness threshold (say a couple of minutes), you could achieve tradeoff between caching and freshness while still conserving resources. If you need absolute freshness, you might have to stick to ETAGs though. If you create a clever hash function, you could handle the ETAG requests on your frontend loadbalancer (or at least near it) which could thus be rather cheap.
Edit: Add alternative from my other comment.
An alternative could be to use added request parameters to force a re-fetch when the resource changed as suggested in another answer. A variation of that schema (which is used by many Rails applications) is to append the timestamp of the last change (or some kind of hash) as a parameter to the file which only changes when the file actually does change. Something like this, or one of the above methods, is actually the only way to be really sure to not have unnecessary cache validation requests while at the same time having always the freshest resource.
Add at the end of the filename a get parameter, such as:
example.jpg?refresh=yesplease
You could also refresh that image each visit by using a rand() param.
In php:
example.jpg?refresh=<?php echo rand(1,999); ?>
Related
I watched a tutorial where they showed that appending ?${new Date().getTime()}to the value of src attribute in the image tag, updates the current image with the new image.
I came across this question, where the first answer to the question has followed the same technique.
Could someone please explain to me the rationale behind the working of this particular technique. Thanks!
Simplest explanation is that the browser (and often the server) will cache items in memory to decrease page load times. Therefore, if you have a dozen pages that all are referencing /images/logo.png, the image is downloaded once and stored so that it can be re-used on each page. Efficient, right?
Anyways, sometimes images change and you don't want that to happen, so what you do is change the name of the file. For example, /images/logo.png?15, /images/logo.png?16, /images/logo.png?17, etc. The browser no longer attempts to use the cached image because the query is actually different.
The code snippet you've included simply includes the current time to the name of the file in order to make it unique.
Different query parameters can result in a server serving different images, depending on the backend logic. This is often not the case - in many setups, requesting the same path with different query parameters will give you the same image in return, but that's not always the case.
If a browser sees an image URL whose image exists in the cache already, it will not download the image again - instead, it'll take the image from the browser cache. But if you change the src to one which is not in the cache, it will make another request to the server. If the server has changed the image at that endpoint between initial pageload and src change, the new image on the server will be downloaded and displayed on the client.
The new Date().getTime() is just a way to append a string which definitely does not exist in the browser cache yet.
We are building a shopping website and need to display hundreds of products and their images. We don't have the product images, but a separate company's service does.
I was given access to this API service. GETting a product image at endpoint https://imageservice.com/api/v3/images/{product_UPC} requires header Ocp-Apim-Subscription-Key.
This returns a response with an array of applicable product image variants. Each image in the response array is at a URL like https://imageservice.com/api/v3/asset/[hash]. These hashed image URLs are one-time use and must be requested with the Ocp-Apim-Subscription-Key again to actually display the image.
This makes the request process to our own API for products difficult as we cannot seed our database with products and their respective image URLs. Instead, each time our shopping site requests products from our own database, we must request the images separately by product ID, loop through the products and match images to each.
Additionally, their service is throttled to about 20 requests every 10 seconds and we load 30-40 products in each paginated call. This will slow the display of products if we don't initially load the URLs into the database.
Question: We already have a paid license and API key to use this separate image API service, and I already have each product in our DB stored with its correct image URL. The problem is we need to pass the header Ocp-Apim-Subscription-Key along with the URL without forming an entirely new AJAX request. How can this be done?
The problem is we need to pass the header Ocp-Apim-Subscription-Key along with the URL without forming an entirely new AJAX request. How can this be done?
If your question is how to query the image without making requests, then short answer is no, you can’t. Headers are made for security reasons. If the target service requires headers and not only URL parameters, then you’ll have to send a new request each time you want to retrieve an image, following each step they require.
I see only 2 solutions
Look further into your API
The API used by the company you retrieve images for may have some deeper options, to allow you more control over it. For example, a function to retrieve many images at once, in one single request.
Take a greater look at it, it might be your best solution.
Not using request
If neither of above proposals fits your desire, then you have no choice but storing images on your own. You deal with an external API, which seem to be private. Thus, you are limited by the work of your partner company, which is totally normal and expected. They may have put those limitations for a good reason, and overpassing them can lead to unsecure behaviors.
If you want maximum control, then you need to handle the most of it by yourself. If you are tied to your partner company work, then you have to see with them what permission they can give you and how you can maximize profits from their work.
EDIT
You can also format your requests, using AJAx or alternatives, such as Axios. Take a greater look at this one. This will, at least, avoid you setting all request parameters on each call.
I am trying to store image in a cookie, but I don't know if this is the best way keep registers from a user when he refreshes the page.
Well, I am using ngCookies module to do that. So I received a image from server in base64 string format, the contentType and the data and then I store in the cookies:
$cookies.contentType = value.image.contentType;
$cookies.data = value.image.data;
To make my url I do this:
vm.url = "data:"+vm.value.image.contentType+";base64,"+vm.value.image.data;
And the url I insert in my page, using img html:
<img src={{ctrl.url}} style="width:200px;height:200px">
My problem is: when I refreshed my page, $cookies.contentType remains, but value.data doesn't stay stored in $cookies.data anymore. I think this value is too big to store in a cookie. I am using cookies correctly? Are there other way to do that?
I appreciate if anyone can help me.
Using cookies for client side storage is generally considered to be less than ideal. Cookies are automatically sent back with every request (if it matches domain/path/security restrictions). Even if the cookie storage limit could handle this I can't imagine you would want to send this back with any future request. LocalStorage and similar technologies were developed in part to avoid this issue.
That said, the http cookie spec originally stated that a cookie needed to accommodate at least 4096 bytes which was then generally interpreted as setting a max size of approximately 4k. Each browser handles this a bit differently and there are plenty of places to read up on it.
I'm trying to determine the best way to cache my JavaScript and CSS files.
There are several ways of doing this:
Using the Date, Expires and Cache-Control headers
Using the ETag header
Cache forever and change the filename when the file changes
Append a querystring to the filename in the HTML with the last mod time or an MD5 of the file contents
I was under the impression that the last method (4) was the most reliable and would result in the fewest unnecessary requests, but my friend just told me that sometimes the querystring method is unreliable and you actually need to change the filename.
Are there any downsides to setting the HTTP headers to cache forever and just using a query-string with the last mod time, or are there scenarios where another method would be more beneficial?
I'm a big fan of method 4, but I use the Session Id, on it. So, a user that enters my website will load it once per session (a session usually dies if the visitor keeps inactive for more than 20 minutes or if he closes the browser window).
In Asp.net, I use that syntax:
<script src="js/DetalhesCurso.js?<%=Session.SessionID%>"></script>
Your third method is the most reliable. Some CDNs/proxies ignore the query string altogether, and just serve the same cached file regardless of the query string value.
Amazon and Azure do support it, but others might not.
Do note that in method #3 you don't actually have to update the filename itself. You can just use some URL rewriting to always get that same file. You'll only have to update your HTML.
So i have a canvas on which the user signs, now instead of converting it to a base 64 string i simply want to save it as an image itslef. whats the easiest way to do it html5??
You can easily do that this way (specifying the format as png in this case):
var img = canvas.toDataURL("image/png");
You can specify different image formats.
Take a look at this answer.
I've answered a similar question here:
Simulating user event
Assuming you are saving locally
You can go the route of creating an image from a Data URL, but then saving it is the trickier part that currently isn't very nice using HTML5. It's hopefully going to get better soon, if browsers incorporate the download attribute of the a tag.
Obviously if you have higher permissions than a standard webpage... i.e. you are designing a browser plugin - then there are other options...
If I were to implement something like this myself, at the moment, I would conceed to using a flash plugin to handle the save to the local computer.
Assuming you are saving remotely
By the sounds of it you aren't saving to a server, but if so this is quite easy by just POSTing the base64 information to a script written in a server-side scripting language (i.e. like PHP) and getting that to write the data directly as binary to a file. Obviously you have to make certain you do this securely however, you don't want just any binary data written to your server's filesystem.
Best of both worlds
If you've got the development time, the best method to get a canvas image saved locally - without Flash - is to create a server-side script that instead of saving the data to your server actually writes the Base64 information you send it directly back as a realised binary image file. That way you can create a form that posts your Base64 data to a new tab, this request is evaluated by the server-side, and the binary image is returned... at which point the browser asks the user where they wish to save their image.
You'll need to define the correct headers to force an image to download (rather than display in-browser). A simple change to force this is to set the server-side script's Content-type header to 'image/octect-stream'... there are other header options to set which would be best researched (i.e. headers that control the filename and so forth).
reflect.php
<?php
/// a simple example..
if ( array_key_exists('data', $_POST) && ($data = $_POST['data']) ) {
header('Content-type: image/octet-stream');
echo base64_decode( $data );
exit;
}
and the form...
<form action="reflect.php" method="post" target="_blank">
<input name="data" type="hidden" value=" ... Base64 put here with JS ... ">
</form>
(The whole form should be created dynamically and submitted automatically with JavaScript)
Improving the user experience
There are ways to avoid a new tab being created, but you'd have to research to make sure these other methods don't cause cross-browser problems... for example you could post your form data as part of an iframe (which would keep the process hidden), or just post the data directly on the current window (..and hope that all the browsers receive the correct request and open a download rather than replace your page content - most modern browsers should handle this).
Improving security
With regards to a PHP script that automatically returns binary data, you should keep the access to this script secured by one time use key / authentication token or something similar, and keep a limit on how much Base64 data you are willing to accept. It might not seem like it poses a secutiry risk - as you are not modifying your server in any way with what the user sends - but the dodgy people of this world could take your script and use it to send download request to other users... which if downloaded (and turned out to be unwanted trojans or viruses) would make your server implicit in providing the dodgy file.
All in all
Due to the effort required to get a simple thing like an image saved to the desktop, I wouldn't blame you for doing the following:
Embed the image in the page (after taking your snapshot from canvas) and ask the user to right click and Save as...
Hopefully future things will make this situation better...