I am using an IHttpHandler to display an image stored in an azure blob on a webpage. This works fine. I also give the user the ability to rotate the image. The code to rotate the image is working. However when I then try to show the rotated image to the user:
document.getElementById("imageControl").src = "/ImageHandler.ashx?container=images&ID=blobFileName;
the image shown on the page is not updated although the image stored at 'blobFileName' has been changed. After some trial and error I found that if I store the rotated blob under a new file name, say 'blobFileNameRotated' the code:
document.getElementById("imageControl").src = "/ImageHandler.ashx?container=images&ID=blobFileNameRotated;
works and displays the rotated file. I assume that the original code doesn't work because the image has been cached by the browser? I tried running the code in a couple of browsers and found that in Chrome the original code works, but only for small files, and that it doesn't work at all in IE11.
My question is how can I control how a browser caches the image file (if that is the problem) and force the browser to re-display the image even if I haven't changed the file name. I tried setting src to a different file and then back to the blob file but that didn't work.
Not really an Azure issue but a few things to try:
You could add a cache-buster to your Image Handler URL. I'd recommend just appending a random number on the end to force the browser to re-request the URL. The problem is no image will ever be cached. Example:
document.getElementById("imageControl").src = "/ImageHandler.ashx?container=images&m=" + Date.now();
Use the same approach but output the number of images to be shown and change Date.now() to am image name / ID so that we as you rotate you will eventually get the same image which should be cached.
// output using some server-side logic.
var imageIds = new Array("ImageA","ImageB","ImageC");
// in an eventHander have similar to:
document.getElementById("imageControl").src = "/ImageHandler.ashx?container=images&ID=" + imageIds[currentImage]
Make sure you set the correct cache headers in your hander's C# code. See Caching ASHX Image Response
Sorry for the slow response to this, my solution was sort of working so I've only just got round to testing out Simon's better solutions. I thought I would add some other things I've found out along the way in case others come to this question looking for information about blobs and images.
My solution involved changing the name of the file each time I rotated it. This meant that I stored a new blob for each 90 degree rotation. This worked but Simon's solution just involves changing the call to the imagehandler so the blob filename doesn't need to change.
I initially ran into problems because I didn't set the content type of the blob after I had rotated it. When I then tried to use the image in a report, the code complained because it wasn't an image type.
Note that if you want to copy the content type from the blob you are rotating it is not available after you have executed:
Dim blob As ICloudBlob = GetBlob(sContainer, blobFileName)
but only after the blob has been downloaded:
blob.DownloadToByteArray(byteData, 0)
This tripped me up at another time as well because I assumed that a blob had been found because I didn't get an error on the dim blob as line of code when in fact it couldn't have been found because I'd passed in the wrong container name.
Happy blobbing.
Related
So, I wanted to avoid the cache to see images I'm uploading to this website I'm working on, which I access through localhost.
I hit a handy solution pretty quick:
Attaching to the end of image's path ?random= and a random number generated by Math.floor(). All this with the help of a script.
The HTML showed in the browser:
<img class="gallery_img" src="./uploads/4.jpg?random=172">
Awesome, it works beautifully.
Now, the thing that has been hard to find is an explanation of why and how this actually works.
I mean, 1) how the browser still finds the image in the server with this new path?
Or asked the other way around, 2) how the server handles this ?random=172 attachment and delivers the image asked before that?
If somebody could point me to the right direction I would be grateful.
Solution:
Have a look on what are query parameters.
And if you are dealing with the problem of avoiding the cache, have a look here:
Disable cache for some images
That is not part of the path, that is a query parameter.
And most of the times the server of images does not care about query parameters, at least not a literally random one, maybe it would support a query parameter called width or size and dynamically generate an image of the correct size. But random is most likely simply discarded and the image is served normally.
I have some issues rising up displaying Image files from local filesystem.
And to say it before: yes i am aware of the security breach this is causing and there is no other way playing it different because my company has no file Server yet to serve these images in a proper way.
With that out of the way the scenario:
I have an angular app which should show me some Images on my page. I wrote a directive called Gallery to do so.
Into this gallery I am handing in the absolute paths to my Image files and just set the src attribute via javascript. I tested it with some random chosen files picked from Google and everything worked out well. Allthough my browser is throwing out error because of security the picutres were displayed.
But when i got the real data from my company collegue Things started getting nasty. The error still thrown in console but nothing was displayed. I checked first overwriting the img.onload listener finding out that the testimages are giving me the Output i put onto the listener, my real data images didn't.
Next I tried to set the background attribute and not the src one. My test images were displayed the real data ONLY if it is placed into the assets folder of my app. This got me quite confused because like mentioned above using my test images it doesn't matter where they are placed, they are displayed everytime.
I also tried changing file format from png to jpg but nothing happens.
Also scaling down the images (real data has big px solutions) didn't work either.
So my question is simple ...what am i doing wrong? Could it be possible that those real data images are not exported properly. But if that's the case, why do they work in the assets folder? Like mentioned security block is not possible because my test pictures a doing well.
Finally I found the bug which was responsible for the behaviour ... It was no wrong linking it was the IIS Express which was caching old links. #mrunion and #cloned links to filesystem are still working on IE and also in Edge just for devs which have no other choice then to do it that way
Cheers Max
I'm wondering is there a JavaScript library available that would allow me to generate an Image from the contents of a DIV.
Basically this is required for some Server-Side Printing code, which needs to print a background from the Browser.
What I'd ultimately like to do would be encode the DIV contents into PNG format and post up the encoded data with the print operation.
Any ideas if this is possible ?
[EDIT] What I have is a mapping application where background data is coming from an image server straight into a browser DIV (Think Google Maps). That div is background to me main data. When Print is pressed the server generates a PDF from the data it knows about, but knows nothing about the browser's background data. What I'd really like is to be able to provide the server with the browsers background image in some way!
Cheers,
Ro
Maybe it's possible with the Canvas:
MDN - Drawing Graphics with Canvas
You can create an image tag from JavaScript but not the actual image in it: JS has no commands to allocate memory for the bitmap and it has no commands to render anything on it.
The usual solution is to have a report generator on the server which creates the image on request. Look at BIRT or JasperReports.
[EDIT] Based on your comment, the solution is simple: Examine the DIV, find the URL for the background image and replace the DIV with an IMG element. Put the URL into the SRC attribute and then print.
Very interesting question.
Actually I solve this problem using ajax (transfer images' positions to the server, server creates one image from pieces, save it and send url to the client). I don't very like this solution but I don't know other yet.
I really don't think this is possible on the browser, certainly not without some kind of plugin.
Could you send some coordinate info or something to the web server and that way have the web server request the same map image from the image server?
Generating images was only possible in IE5 :( Then due to security reasons it was dropped. I'm still missing it.
I think I've worked out a way to do it.
1) When the user presses Print, interrogate the DIV
2) Images on that DIV are being generated by the OpenLayers API
3) Grab the URL of each Image
4) Grab the location on screen of each image
5) Translate the screen location into a Real-World location (I have API for this)
6) As part of the print send up all the image URL's along with their real-world extents
7) Allow the server to re-request the Images and draw them into their appropriate locations.
Does it have to be done on the browser side? I have seen where you can do a server side call and the MIME type on the server response is the image type. I think the example I'm thinking of was for b64 encoded jpegs in a db, but the process should be the same. The response would be the data that is currently in your DIV. Sorry if I'm way off base.
If you make a new image and define is source do you need to preload? For example:
var image = new Image();
image.src = 'data:image/jpeg;base64,/9j/4Q+sRXhpZgAATU0AKgAAAAgABw...';
// Append image to canvas.
I've been doing some tests but I'd rather rather have reliable evidence, so links would be nice.
Thanks
EDIT: Actually I may have been wrong apparently different browsers behave differently in this respect and although the image is available information such as it's width and height aren't necessarily. I assume this is because the browser functions that calculate this information are non-blocking and assume you are listening to onload.
So yes listen to the onload event to ensure that a dynamic image has been loaded by the users browser before attempting to use it.
Based on information from: Should setting an image src to data URL be available immediately?
Ignore the following advice (it remains to provide context to my answer):
By storing it as a variable you are in a way preloading it. All that happens when you preload an image is it's data is retrieved and stored. You have already stored it's data in a variable - what is there to preload?
Because variable assignment is synchronous the image will be available to your code that follows.
The whole point of preloading is the fact that an image is usually at a different location on the server and that loading of separate files is often asynchronous thus you ensure that your script waits for the image to be downloaded. By creating your image inline you are effectively storing it in the JavaScript file and it will be downloaded at the same time.
so you select an image via the file input, the selected image file gets gets turned into a window.url.createobjecturl and passed to a hidden "img" element unmodified, then a preview of the image element's current data is rendered into a canvas element. so far, so good. but then when i try to render the canvas.toDataURL i keep getting that aggravating security exception about it being insecure. this happens on chrome and firefox.
understand that this is a file OBJECT that was select with an html INPUT element, and NOT via a "file://" url, and the webpage is an actual webpage, and is loaded via "http://" and not via "file://".
the image file has not even left the browser yet to go to the server, so there should not be any domain issues. it's just a raw blob being asserted as the source to an image, which is then telling the canvas to update its preview, which it does. after that, when trying to saved the canvas contents, the browser triggers an error.
i have read all of the specs regarding scenarious where the canvas element becomes tainted, and this scenario does not meet ANY of those scenarios.
i've seen a similar example on mozilla demos of some one offering code snippets to show people how to do the same thing, but i have not seen if any one had problems with it.
any ideas? TIA
#
=== UPDATE ===
#
okay, i've figured out what the PROBLEM is, but i'm still not clear on WHY it's a problem. here's the setup:
1) page is called via, eg, "example.com/"
2) script is called via: "r.example.com/script.js"
3) if script loads ANY image from "r.example.com", to use for the PAGE DESIGN, and NOT the canvas, it some how taints the entire page. in this case i draw the entire page via javascript, so the header image is tainting the rest of the page. if i change the header image to come from "example.com" instead of "r.example.com", the problem with the canvas complaining about not being secure goes away, and everything is fine.
what i don't understand is WHY this is happening. the header image is being loaded from the same place as the javascript file, and, for the sake of argument i even set the access-control-allow-origin to "*", for both the main domain and the subdomain, which makes no difference.
so, access control is allowed from anywhere, the header image is coming from the same place as the javascript file, and it is NOT being drawn to the canvas (that's a user file), so why would drawing the header image via javascript taint a canvas that it has nothing to do with??? also, the css and other media are loaded from the same subdomain, but this does not affect the page, so long as the script did not load them [o_0].
i want to keep all of my resources on a separate subdomain for scalability, so, this issue is frustrating, because i don't quite understand why it's still happening...
If you want your image to be on a separate subdomain, you have to change the origin of the image to allow all subdomains like this:
img .origin = '*.mydomain.com'
I'm using canvas with kineticJS and just tested it myself.
it appears that you have to set this property on the image object itself, as it has no domain initially [o_0]
img.origin = 'mydomain.com'