Determine through javascript if another URL exists - javascript

I am working with a servlet which serves up an image. However, it takes about 30 seconds for this to be generated. When complete, it appears on an OpenLayers interactive map.
I am trying to figure out a way for the user, who is at www.test.com to get confirmation the image is being processed or is complete, which is located at www.test2.com. If I open test2.com, I can see that the page is trying to load. When complete, the image also appears on my map on test.com.
However, I can't figure out how to test if this image exists or not. I am looking for something probably like
if(image exists at http://test2.com) {alert("request is done");
or possibly
if(http://test2.com is loading) {doing something);
I just don't want the user sitting by if the request fails. If it fails, the url will complete its load - however, no image will appear. Any guidance will be very appreciated! Thanks!
Kyle

If it is a different server, JavaScript will not be able to make any type of Ajax request to that server to see if it exists. You would have to have a proxy on the local domain which could make a head request to the second domain.
If you are waiting until the image is loaded to work with it, you can always do an image preloader, but that will take the full time for the image to render before the onload event fires.
var img = new Image();
img.src = theUrl;
img.onload = function() {
nextStep(this);
};
img.onerror = function() {
imgLoadingError(this);
};

IF you have control over the other server, you could put a small image on that server and do something like this: (Untested code, typed in directly)
var img = new Image();
// Note the order of these two statements
img.onload = function()("The image loaded! Server must be up");
img.src = "http://example2.com/myflag.png";

Related

Get pixel data back from programmatically generated image

I generate array of pixels in client side JavaScript code and convert it to a blob. Then I pass URL of the blob as image.src and revoke it at image.onload callback. I don't keep any references to the data, generated by the previous steps, so this data may be freed by GC.
There are many images generated this way, and it works fine. But sometimes user may want to save the generated image by clicking on a Save button near the image. I don't want to generate image again, because generation is slow, and the image is already generated and is visible on screen. So I want to get my pixels back from the image. I tried to create canvas again, draw image on it and then call toBlob, but browser treats this image as cross origin and throws an exception: "Failed to execute 'toBlob' on 'HTMLCanvasElement': tainted canvases may not be exported". Similar errors I get with canvas.toDataUrl and canvasContext.getImageData.
Is there a workaround for this problem?
I also tried to create canvases instead of images, but when I create the second canvas, the content of the first one clears.
Added
This error occurs only in the Chrome and other WebKit browsers. Firefox and MS Edge work fine. And when I commented out line of code that revoked blob url, this error disappeared - I can draw the image on the canvas and get its pixel data without CORS issues. But it is pointless to do so, because I already have blob that is not deleted.
But my page may generate many images - it depends on its user and is unlimited. Size of images is also unlimited - it may be useful to generate even 4096x4096 images. So I want to reduce memory consumption of my page as much as possible. And all these images should be downloadable. Generation of most images uses previously generated images, so to regenerate last image in a chain, I must to regenerate all images.
So I need a workaround only for Chrome browser.
Added 2
I tried to reproduce this problem in JS Fiddle, but couldn't. However locally my code doesn't work - I developed my app locally and I haven't tried running it on server. Create test.html file on your computer and open it in browser (locally, without server):
<html>
<body>
<pre id="log"></pre>
</body>
<script>
var log = document.getElementById("log");
var canvas = document.createElement("canvas");
canvas.width = canvas.height = 256;
var ctx = canvas.getContext("2d");
canvas.toBlob(function(blob) {
var img = new Image();
var blobUrl = URL.createObjectURL(blob);
img.src = blobUrl;
img.onload = function()
{
URL.revokeObjectURL(blobUrl);
ctx.drawImage(img, 0, 0);
try { canvas.toBlob(function(blob) { log.textContent += 'success\n'; }); }
catch(e) {log.textContent += e.message + '\n';}
};
});
</script>
</html>
It will print Failed to execute 'toBlob' on 'HTMLCanvasElement': Tainted canvases may not be exported..
So, I think, my workaround is to detect that page is run on combination of WebKit browser and file:/// protocol. And I can to defer revoking blob URL until page unload only for this combination.
That indeed sounds like a bug in chrome's implementation, you may want to report it.
What seems to happen is that chrome only checks if the image has been loaded through a clean origin when it is drawn for the first time on the canvas.
Since at this time, you already did revoke the blobURI, it can't map this URI to a clean origin (file:// protocol is quite strict on chrome).
But there seems to be a simple workaround:
By drawing this image on a [the reviver]* canvas before revoking the blobURI, chrome will mark the image as clean, and will remember it.
*[edit] Actually it seems it needs to be the same canvas...
So you can simply create your export canvas before-hand, and draw each images on it (to save memory you can even set it to 1x1px when you don't use it for the export) before you do revoke the image's src:
// somewhere accessible to the export logic
var reviver = document.createElement('canvas').getContext('2d');
// in your canvas to img logic
canvas.toBlob(function(blob){
var img = new Image();
img.onload = function(){
reviver.canvas.width = reviver.canvas.height = 1; // save memory
reviver.drawImage(this, 0,0); // mark our image as origin clean
URL.revokeObjectURL(this.src);
}
img.src = URL.createObjectURL(blob);
probablySaveInAnArray(img);
};
// and when you want to save your images to disk
function reviveBlob(img){
reviver.canvas.width = img.width;
reviver.canvas.height = img.height;
reviver.drawImage(img,0,0);
reviver.canvas.toBlob(...
}
But note that this method will create a new Blob, not retrieve the previous one, which has probably been Collected by the GarbageCollector at this time. But it is unfortunately your only way since you did revoke the blobURI...

Retrieving image data URi from HTTP response

The Problem: Imagine I have a td element structured as such:
<td td="" colspan="2">
<br>
<img src="ImageServlet" alt="random image" border="0" id="simpleRandomImg">
</td>
of course, with other HTML around it. The image contained within the servlet doesn't have a useful src indicated in the HTML (clearly) - however, when I open up the Network tab in Chrome, I can preview the loaded image itself and copy the image as a data URI - which gives me a stable URL like:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAyCAIAAACWMwO2AAAhQklEQVR42u2dB1Sb5/nonTRt2pPkJGmSNm180zhNTkabuPGKMeAwxBaIJYEYWmhLSEIggRhaaAIaIEASEggQew+zzPLEdjyy07T/9t9129t129u9z7mP9LnfXxZCBuLeS/71c77zIRQCGj89z+993+d7vS/GH7GxsXH+wGAwCf5ITExMSkpKTk5OSUlJTU1N80d6etcetcetc...
so, clearly there exists a stable reference to the loaded image. And clearly my browser 'knows' what that reference is, because I can retrieve the link to it as a data URI - but there's no reference to that data URI in the actual HTTP response. This probably seems a lot less mystical to someone who understands JavaScript, but that someone is not myself - so could someone explain what's going on here, and if there is some way to gather the data image URI from the HTTP response?
Attemped Solutions:
Did a little digging around in the HTTP response and located this bit of JavaScript which, apparently, handles the changing of images:
function changeImage() {
// makes a new image load
var obj=document.getElementById('simpleRandomImg');
if (obj != null) {
// append a unique index to force browser to reload
obj.src='ImageServlet?'+(cnt++);
}
However, nothing I see there gives any indication as to the actual URI location of the image. As before, if I open the Google Chrome network tab and attempt to retrieve the data image URI from the individual response, it works and gives me a valid URI - so, clearly the browser is receiving it. How can I access it?
e: to be clear, I do not control the website in question, so I can't 'fix' it by just changing the internal javascript - I'm viewing the site and am interested in whether or not it's possible to retrieve the loaded images short of screenshotting the page itself.
Something like this should work. Canvas API has a function called toDataURI
function getDataUri(url, callback) {
var image = new Image();
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
canvas.getContext('2d').drawImage(this, 0, 0);
// Get raw image data
callback(canvas.toDataURL('image/jpg').replace(/^data:image\/(png|jpg);base64,/, ''));
// ... or get as Data URI
callback(canvas.toDataURL('image/jpg'));
};
image.src = url;
}
// Usage
// beware of server cors settings..
getDataUri('image url here', function(dataUri) {
console.log(dataUri)
// Do whatever you'd like with the Data URI!
});
You can set the src of the image to your URI by using setAttribute, like so:
obj.setAttribute('src', uriString)

Why isn't phaser.js able to load an image from a third-party domain?

I'm learning phaser.js, and I cant even load the image.
Here is the code:
// Need state. All game logic goes in state
var GameState = {
// Load all your images. Thats what the preload function is
preload : function(){
//Load Image
this.load.image( 'background', 'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSMxwX5oTml7qBFmUD3vEIzEhqLQfakBVjmkQezA8HKs4KnT-2Q' );
},
//Execute after everything is loaded
create: function(){
//From top left param = (x,y)
this.background = this.game.add.sprite(0,0, 'background');
},
update: function(){
}
}
// New Game instance, 3rd parameter WEBGL or CANVAS automatic GL
var game = new Phaser.Game(640,360,Phaser.automatic);
// add state to game
// First just a name, second par is the actual Object
game.state.add('GameState', GameState);
game.state.start('GameState');
And here is the image that clearly shows that it doesen't load:
Your image isn't showing up because Phaser can't make use of cross-origin images, so all images need to be loaded from the same origin. In practice, this means that instead of loading the image directly from gstatic.com, you need to first download the image to your computer, then move it to your Phaser project folder and load it using a relative path.
For more information, please see the Wikipedia article on the Same-Origin Policy.

How long does a Blob persist?

I'm trying to write a fail-safe program that uses the canvas to draw very large images (60 MB is probably the upper range, while 10 MB is the lower range). I have discovered long ago that calling the canvas's synchronous function toDataURL usually causes the page to crash in the browser, so I have adapted the program to use the toBlob method using a filler for cross-browser compatibility. My question is this: How long do Blob URLs using the URL.createObjectURL(blob) method last?
I would like to know if there's a way to cache the Blob URL that will allow it to last beyond the browser session in case somebody wants to render part of the image at one point, close the browser, and come back and finish it later by reading the Blob URL into the canvas again and resuming from the point at which it left off. I noticed that this optional autoRevoke argument may be what I'm looking for, but I'd like a confirmation that what I'm trying to do is actually possible. No code example is needed in your answer unless it involves a different solution, all I need is a yes or no on if it's possible to make a Blob URL last beyond sessions using this method or otherwise. (This would also be handy if for some reason the page crashes and it acts like a "restore session" option too.)
I was thinking of something like this:
function saveCache() {
var canvas = $("#canvas")[0];
canvas.toBlob(function (blob) {
/*if I understand correctly, this prevents it from unloading
automatically after one asynchronous callback*/
var blobURL = URL.createObjectURL(blob, {autoRevoke: false});
localStorage.setItem("cache", blobURL);
});
}
//assume that this might be a new browser session
function loadCache() {
var url = localStorage.getItem("cache");
if(typeof url=="string") {
var img = new Image();
img.onload = function () {
$("#canvas")[0].getContext("2d").drawImage(img, 0, 0);
//clear cache since it takes up a LOT unused of memory
URL.revokeObjectURL(url);
//remove reference to deleted cache
localStorage.removeItem("cache");
init(true); //cache successfully loaded, resume where it left off
};
img.onprogress = function (e) {
//update progress bar
};
img.onerror = loadFailed; //notify user of failure
img.src = url;
} else {
init(false); //nothing was cached, so start normally
}
}
Note that I am not certain this will work the way I intend, so any confirmation would be awesome.
EDIT just realized that sessionStorage is not the same thing as localStorage :P
Blob URL can last across sessions? Not the way you want it to.
The URL is a reference represented as a string, which you can save in localStorage just like any string. The location that URL points to is what you really want, and that won't persist across sessions.
When using URL.toObjectUrl() in conjuction with the autoRevoke argument, the URL will persist until you call revokeObjectUrl or "till the unloading document cleanup steps are executed." (steps outlined here: http://www.w3.org/TR/html51/browsers.html#unloading-document-cleanup-steps)
My guess is that those steps are being executed when the browser session expires, which is why the target of your blobURL can't be accessed in subsequent sessions.
Some other discourse on this: How to save the window.URL.createObjectURL() result for future use?
The above leads to a recommendation to use the FileSystem API to save the blob representation of your canvas element. When requesting the file system the first time, you'll need to request PERSISTENT storage, and the user will have to agree to let you store data on their machine permanently.
http://www.html5rocks.com/en/tutorials/file/filesystem/ has a good primer everything you'll need.

Load image... when time is eating up

here is a sameple code, I would like to know when the browser is REALLY loading image
when you assign an image path to a array like that
imageNames[0] = 'image1.jpg';
or when you make
myImage = new Image();
myImage.src = imageNames[0];
i have put some timer.. but did not get concluant result ! HELP
You would look at the load event. Attach it with the ancient onload or addEventListener()/attachEvent() depending on your browser support requirements.
myImage = new Image;
myImage.onload = function() {
alert('Image loaded');
}
myImage.src = imageNames[0];
jsFiddle.
You could also check if the image is already loaded by checking the complete property.
The key thing to note is that just because a human being can see that something could be a resource identifier / locator, the computer cannot.
When you assign a string to a point in an array:
imageNames[0] = 'image1.jpg';
the fact that 'image1.jpg' is a licit path to an image on your.host.net is not something the browser can determine on its own - the browser cannot recognize that the string 'image1.jpg' is a resource representation rather than a resource itself.
Once you set a DOM image's src property to be the string 'image1.jpg' the browser can recognize the string should be treated as a resource identifier (because the DOM element you created is an image, and the image's src property is supposed to be a URI pointing at an image resource which can be accessed and downloaded) and the browser will try and acquire that resource through means of its own.
The browser downloads the image when you assign a URL to the src attribute of an img element. Try this in the console of your browser and watch the Network tab:
var img = document.createElement('img');
img.src = 'foo';
You'll see network activity as soon as that second line executes.
It most certainly does nothing for imageNames[0] = 'image1.jpg'; since a string in an array could be anything, there's no way the browser has any idea this is supposed to be the URL of an image.

Categories