I have a small http server which generates some images on-the-fly, and the generation process may take some time. After generation, the image is cached indefinetly.
Currently, if a user requests an image which is not cached, the server returns a 202 Accepted with a Refresh header. If the image is cached, a 301 Permanently Moved is sent and the user redirected to a unique url (different images may share the same unique url).
The whole system breaks if the image is referenced in an <img> tag (on Firefox, at least). Can this be solved without Javascript? If not, how would the script look like?
Im not sure if you can do it without Javascript but you could probably do this with ajax? I mean, point at the server and then just check to see if it is there... then if it is display it, else try again 30 seconds later, it could be something like:
function getImage(img) {
$.ajax({
cache: true,
url: <<ADDRESS>>,
data: "",
timeout: 60,
error: function (jqXHR, error, errorThrown) {
setTimeout(function() {
getImage(img);
}, 30000);
},
success: function (data) {
//set the image
}
});
}
Okay your then hoping that the image will come down at somepoint.
The only other option would be to generate the image before it is requested? For example if it is just creating a thumbnail for a photo gallery, why wait until it is requested to generate it? Just generate it as soon as you have it?
Hope that helps / makes sense.
Related
I wanted to send a PNG Data Url with Ajax to my PHP-Script but the Url on the Client Side is not the same that i recive with PHP.
$.ajax({
url: "proceed.php",
type: "post",
data: "signature=" + signaturePad.toDataURL('image/png'),
error: function(e) {
alert("ERROR");
console.log(e);
},
success: function(e) {
alert(e);
}
});
I think it gets damaged while sending - maybe a encoding problem?
I Already tried to encode the URL with JSON but it's the same problem...
data: "singature=" + JSON.stringify(signaturePad.toDataURL("image/png")
I presume you are using HTML5's canvas.toDataUrl() as described here.
Your image data is not the same, because instead of sending the actual image, you are sending the data of the image that is painted on your site.
As the browser is throwing away unneeded data and (probably) keeping only RGBA and size information, the image you receive is understandably 'mangled'. Documentation also states that the image resolution will always be only 96 dpi.
There could also be problems arising from using URI component for transfer of "binary data" (these quotes are supposed to be huge). There seems to be no set lower or upper bound for URI component, as stated here. I would suggest using this technique only in case of small (IMHO around 40x40px) images.
Refer here on how to send bigger images over jQuery's $.ajax().
There can be different reasons for <img> load errors, such as network error response, bad image data...
error object received from onerror doesn't seems to specify the exact reason.
Is there a way to know if the error is because of a network error, say HTTP 500 or a network timeout?
EDIT:
I'm not looking for an alternative way to load a resource, such as AJAX request. I need an answer specifically for <img> tag with onerror event. The reason for that is that I'm using this method for pixel-tracking and I need a way to retry on upon network errors. I'm also not looking for alternative tracking methods such as JSONP.
Edit 16Nov16 2020GMT
Maybe you are pixel-tracking in emails or other clients limited in Javascript capabilities.
One idea that comes to mind is to use URL query paramters in your <img>'s src URL.
With regards to network timeouts, I will pose the idea that a user opens an email, loads the email entirely, then disconnects from the internet and somehow this does not give the tracker enough time to load.
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
I would suggest to use setTimeout() inside your onerror function.
This will continue attempting to set/load the <img>'s src URL. You could append the seconds it took until successful load to the URL of your src file as a query parameter like ?s=<sec>
As far as determining status 500 codes on image loads you might want to consider creating a custom 500 error file which would then create -- for example -- a MySQL database entry with all sorts of information you have access to and if you chose to use the query parameters mentioned before then you have slightly more information added to the error.
onerror for <img> gives limited information about the network
The information that is available from <img> can be found at
https://www.w3.org/TR/html/semantics-embedded-content.html#htmlimageelement-htmlimageelement
Older answer:
Perhaps a route you would like to try is to use AJAX to load the image data and set the <img> src to the base64 of the image data received. I hope this helps.
Edit 14Nov16 2018GMT
Alternatively use AJAX to determine if the image loads properly and then use the same URL sent to AJAX as the src for your <img>. It would of course be redundant but would avoid the issue of long "data" URLs.
Edit 15Nov16 0832GMT
Also regarding Network Timeout I found this thread to be useful JQuery Ajax - How to Detect Network Connection error when making Ajax call
Apparently you can specify a timeout to AJAX much like using error except you just provide the miliseconds manually.
Converting to Base64
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa
var encodedData = window.btoa("Hello, world"); // encode a string
Or if you are concerened about older browsers able to use btoa() then you might be interested in Google's https://chromium.googlesource.com/chromiumos/platform/spigots/+/refs/heads/firmware-u-boot-v1/base64_encode.js
Status Code checks in jQuery's AJAX
jQuery: How to get the HTTP status code from within the $.ajax.error method?
$.ajax({
type: 'GET',
url: '/path-to-my/image.png',
data: null,
success: function(data){
alert('horray! 200 status code!');
// convert to base64; add to img.src # btoa(data)
document.querySelector("#hlogo img").src = "data:;base64,"+ data;
},
error:function (xhr, ajaxOptions, thrownError){
switch (xhr.status) {
case 400:
// Take action, referencing xhr.responseText as needed.
case 404:
// Take action, referencing xhr.responseText as needed.
case 500:
// Take action, referencing xhr.responseText as needed.
}
});
Notes
https://www.rfc-editor.org/rfc/rfc2397#section-3
dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
mediatype := [ type "/" subtype ] *( ";" parameter )
data := *urlchar
parameter := attribute "=" value
https://www.rfc-editor.org/rfc/rfc2046#section-4.2
Using of a generic-purpose image viewing application this way
inherits the security problems of the most dangerous type supported
by the application.
https://www.rfc-editor.org/rfc/rfc2397#page-4
The effect of using long "data" URLs in applications is currently
unknown; some software packages may exhibit unreasonable behavior
when confronted with data that exceeds its allocated buffer size.
Other References
Unknown file type MIME?
Asynchronously load images with jQuery
I have a dumb network device that has limited HTTP hosting capabilities and I'm trying to write a slightly more dynamic page to display data with. A some current process values can be found in plain-text at /temp.dat on the device, but my stone-simple jQuery script...
$(document).ready(function() {
$('#temp').load('/temp.dat');
var refreshId = setInterval(function() {
$('#temp').load('/temp.dat');
}, 2000);
$.ajaxSetup({ cache: false });
});
...seems to endlessly fail (only after the first .load on the initial page load) because the device abhors HTML query parameters. Chrome's JS console shows endless errors like the following:
GET http://192.168.1.250/temp.dat?_=1341980712854
How can I get jQuery (or pure JavaScript) to hammer away at a specific URL without attaching the HTML query (...?_=123456789)?
You should be able to add this at the top of the script
$.ajaxSetup ({
cache: true
});
when console outputs GET http://192.168.1.250/temp.dat?_=1341980712854, thats not an error, thats the log of the attempt to perform that task. When its colored red, it means that the HTTP GET of that particular address returned an error (like a 500).
I am not trying to ask for free ride, but I don't seem to know how to do this at all.
My recent posts are about running jobs in the background, but I have no luck in doing that.
So...
User clicks run inside a form and it fires a job.
It takes about 30 seconds to complete the job, returns, and tells Django view function to return HttpResponseRedirect(....).
So while the page is being redirect (it takes 30 seconds to signal "GO AHEAD").... I want to show user like an Ajax loading gif picture.
I don't have Ajax implemented and the system is way too complicated to hack on.
Can we actually do this with javascript? The problem is that it hasn't load any page yet because it needs heavy_work to finish.
result = heavy_work(....)
.... more code ....
return HttpResponseRedirect(go to this page...)
Thanks!
Why don't you use a regular ajax call?
javascript
function do_heavy_lifting(argument) {
$.ajax({
type: 'GET',
data: { argument: argument }, // if necesarry
url: '/heavy_lifting_django_view_url/',
beforeSend: function() {
$('#loading').show();
},
success: function(data) {
...redirect...
},
cache: false
});
}
html
<div id="loading" style="display:none">
<button onclick="do_heavy_lifting('argument');">
Using AJAX is simple: just show a 'loader' animated gif before the actual ajax call, and in 'on_success' response callback to hide the loader gif.
Bu without AJAX - the only solution so far is using iterators - look at this: How to stream an HttpResponse with Django
I have built an uploader for my application but struggling on something.
Every 3 seconds my AJAX script makes a call to my ASP page, checkProgress.asp, to check how many files are in that folder during upload, it also checks if a txt file called complete.txt is in there.
When the count is done, it sends a response back to the AJAX script with something like "File 2 uploaded..." and 3 seconds later it will send "File 3 uploaded...", and so on. If the complete.txt file was found, it would return "Complete" instead of counting. This worked fine, once, and then didn't seem to perform properly after that. I get the "complete" message as I should but not getting the file count progress response.
I ran the checkProgress page manually with a new browser window to see why my progress panel was not updating with the progress, and noticed that the browser loading icon was just spinning, and when the upload finished, "Complete" popped up. So the AJAX call wasn't reaching the page to gather the count of files because it was busy, which confuses me, because all that page is doing is counting how many files are in a folder.
Can somebody suggest what I'm doing wrong? Is this just simply not going to happen while that folder is being added to?
Here is my AJAX script. This starts when the upload starts:
var upload1ProgressCheckInt = setInterval(function() {
var postData = "token="+token;
$.ajaxSetup ({ cache: false });
$.ajax({ type : 'GET', url : 'ajax/checkProgress.asp',
dataType : 'html', data : postData,
success : function(data) {
if (data == "Failed") {
$('#upload1ProgressStatus').html('Error: Upload cancelled!');
clearInterval(upload1ProgressCheckInt);
// do stuff
} else if (data == "Complete") {
$('#upload1ProgressStatus').html('Success: Files uploaded');
clearInterval(upload1ProgressCheckInt);
// do stuff
} else {
$('#upload1ProgressStatus').html(data);
}
}
}); // end ajax
}, 3000);
and this the checkProgress.asp page:
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
If (FSO.FileExists(Server.MapPath("../files/photos/"&token_&"/complete.txt"))) = True Then
Response.Write "Complete"
Else
Set folder = FSO.GetFolder(Server.MapPath("../files/photos/"&token_&"/"))
Set files = folder.Files
fileCounter = files.Count
Response.Write "File "&fileCounter&" uploaded..."
End If
...continuing from comments.
So here is how I understand it. Classic ASP assigns a worker thread to each session, because Classic ASP object are single threaded, and thus the only way to share them (stored in the Session object) between requests is to have a single thread for each session. Naturally that means exactly what you are seeing - all other requests are blocked until upload finishes.
Way to work around that would be to break out of the session. Unfortunately session cookie is HTTP-only (for security reasons), so I don't think there is a way to drop it from AJAX request.
You could make your IIS entry respond to another hostname and convert your AJAX request into JSONP request to that second hostname. I am not sure if there is a more graceful way to do it.
==================
EDIT: Actually I take back the part about cookies. Surely you can kill them by giving headers:{Cookie:""} to your ajax() call? Worth a try....