Fetch download progress in a content script - javascript

I fetch some data and display it on a web page after that. It works OK.
I want to show the downloading progress on the web page, but the next code does not work in a content script properly.
(async () => {
const response = await fetch("https://i.imgur.com/Rvvi2kq.mp4");
const reader = response.body.getReader();
const contentLength = +response.headers.get('Content-Length');
alert(contentLength) // 0
// other code...
})();
It works properly (shows 2886550, not 0) only if I run it in the context of the page in the same domain (i.imgur.com for this example).
Does it can work (properly) in a content script or at least in a background script? And works when I fetch a data from not the same domain too?
Is there any way to fetch a data (not just download to Downloads folder) for working with it after that and see downloading (fetching) progress?
Upd: The code above* works properly in the background script, but only in Firefox and Chromium 76+ based browsers. It was a Chromium's bug, that the code shows 0.
*It's a part of the code from here.

Imgur.com's server does not send a Access-Control-Expose-Headers header exposing content-length, so download progress indicators are not possible. It could possibly be faster to serve static content with HTTP/2 from your own domain/server since you would not be opening new socket connections to other CDNs. You could also use your server as a proxy to Imjur.com, but you run the risk of them blocking your server's IP
The fetch-progress-indicators examples show various download progress indicators with Fetch.

Related

Stop browser caching images to disk

I'm developing a local application that displays sensitive images from a secure local server and I need to ensure those images are only viewable inside my web application - so I don't want them stored on disk (via cache or anything like that).
Here are my response headers (nodejs express):
res.header("Cache-Control", "no-cache, no-store, must-revalidate");
res.header("Pragma", "no-cache");
res.header("Expires", "0");
res.send(image);
Here is my AngularJS code to get the image and render it. I'm using AJAX because I'm authenticating the user via JWT so I need to include the auth header.
$http.get(src, {
responseType: 'arraybuffer'
})
.then(function(res){
var headers = res.headers();
var blob = new Blob([res.data], {
type: headers['content-type']
});
image.src = $window.URL.createObjectURL(blob);
});
It seems to work but I'm confused as to what the Chrome and Firefox developer tools are showing me. I need to be 100% sure these images aren't stored on disk.
But I see:
Status Code: 200 OK (from cache)
Chrome Dev Tools Image
I can't see the image in the chrome://cache tab but it worries me that I'm seeing (from cache) in the network monitor.
In my Firefox cache viewer I see the url to the image but the device column says "memory". Can anyone who's looking at memory view it after some period of time, especially after a user has logged out?
Firefox cache viewer
So I guess my real question is what are these two browsers doing when I create a blob? And can anyone access these images outside the browser? What does it do on a mobile/tablet device?
If I were to transfer the image using a base64 string, would that be safer or worse in terms of privacy and security?
Yoy can convert jpg blob to canvas image data, by jpg.js and then load it to a canvas, and don't use images, in this case, there are any no images and resources to load by HTTP.

Web Worker: How to prevent that file gets loaded from cache?

This is incredibly annoying.. I am wondering why the heck my changes aren't reflected as I notice that my JavaScript file for my Web Worker always gets loaded from cache:
I have disabled the Cache and hitting Ctrl + F5 does not work either.
How can I make sure that this file does not get loaded from cache?
_worker = new Worker('js/toy-cpu.js');
You could add a kind of version number, for example like this:
_worker = new Worker('js/toy-cpu.js?v=' + new Date().getTime());
If you are looking for the purposes of development / the configuration of your personal machine.. rather than that every user needs it to load from the web server.
Chrome has an option to disable cache
Notice the checkbox "disable cache" that you can check as I have.
And in the section below, where it says "Perform a request". if you refresh then you see the page listed, and it can indicate whether a URL is loaded from the web server, if chrome says 200 and if in the size column it gives size as a number, then it loaded from the web server. And if you double click a URL in the inspector, you see HTTP Headers.

How to force an update of a Single-page application

I work on a AngularJS Single-page application which once loaded (all the resources are fetched from the HTTP server) only accesses the REST backend to get/send data. The task is how to make sure users are always using the latest version of the frontend code (.js, .css and .html files) when the users never leave the page and never refresh the browser.
I think there are several options:
the frontend asks the HTTP server every N minutes what is the latest frontend code version
the backend includes the latest frontend code version in every response (e.g. an additional HTTP header) which is inspected by the frontend code
the backend returns a cookie with the latest frontend code version and checks if the version provided by the user is outdated
websocket connection between the browser and the backend (not an option for me)
Do you know other approaches?
you can also use html5 application cache, this way every time something changes, the website will update itself in the first visit, pretty handy and faster than ordinary cache.
Recently I have used the 2nd approach in my Agnularjs SPA. What I did is
In my angularjs APP's .htaccess and my API Server's .htaccess I have added a header:
<IfModule mod_headers.c>
Header add appVersion "1.2"
</IfModule>
Now I will receive this header whenever I am getting anything from API server or frontend(js, html, css, images)
now in my index.html i have defined a variable something like
var frontendVersion = 1.2
I have a http Response interceptor that will look for each response and I have done something like this
myAPP.factory('httpRespInterceptor', function () {
return {
response: function (response) {
var appVersion = response.headers('appVersion')
if(appVersion == frontendVersion) {
console.log('ok')
} else if (appVersion != null) {
location.reload();
}
return response;
}
};
});
I have added a null check because when i am loading a same view twice I am getting Empty Header Object and in my console i don't see any request that is being sent to the server..don't have a clue why this is happening if someone can shed a light it will be grateful :)
so whenever I will make a change in my code/update the application i will change my header appVersion to 1.3 and my index.html variable to var frontendVersion = 1.3
I hope this helps. And also Please let me know if there are best solutions other than this,
Thanks,

Why do I have differences with AJAX hosted local vs remote?

I guess part of my answer relates to "same-origin" but I'm not still not absolutely clear on when it applies and when not (or why it works in one instance, but is not a solution in other cases).
I am using latest jQuery, jQuery mobile and Apache/MySQL/PHP stacks. Client is either Windows 7/Firefox 38, or iPad/PhoneGap.
My AWS hosted php code serves the following to help resolve "same origin":
$http_origin = $_SERVER['HTTP_ORIGIN'];
header("Access-Control-Allow-Origin: $http_origin");
The Phone Gap version of my app works as expected, retrieving data from my AWS server and rendering the data it has retrieved.
Calling the exact same code from my laptop browser fails. Why?
If I copy/paste the AJAX URL into my browser, it correctly pulls the JSON data from AWS.
In an effort to resolve, I dump output to console.log. The jQuery AJAX "error" section gets called instead of the "success" portion. The same "error" result occurs if I call the index.html file (which calls JS) using File Open within Firefox, or if I call the locally apache hosted index.html file, jQuery ajax jumps to "error" section.
So if my phonegap app works, but my laptop does not, why? I mean, I see my app being akin to the laptop web browser. They both in effect have a different origin than my web server so I would expect either both work, or both fail.
If someone can help clarify it would be great - I have twice spent time chasing a problem that only exists in my dev environment but works just fine in production - its frustrating!
Thanks all in advance
Have you white listed domain in your phonegap config ?
http://docs.phonegap.com/en/4.0.0/guide_appdev_whitelist_index.md.html
ex:
Access to google.com:
<access origin="http://google.com" />
__ reading it should improve : https://github.com/phonegap/phonegap-app-developer/issues/169 __

Why do browsers inefficiently make 2 requests here?

I noticed something odd regarding ajax and image loading. Suppose you have an image on the page, and ajax requests the same image - one would guess that ajax requests would hit the browser cache, or it should at least only make one request, the resulting image going to the page and the script that wants to read/process the image.
Surprisingly, I found that even when the javascript waits for the entire page to load, the image request still makes a new request! Is this a known bug in Firefox and Chrome, or something bad jQuery ajax is doing?
Here you can see the problem, open Fiddler or Wireshark and set it to record before you click "run":
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<div id="something" style="background-image:url(http://jsfiddle.net/img/logo-white.png);">Hello</div>
<script>
jQuery(function($) {
$(window).load(function() {
$.get('http://jsfiddle.net/img/logo-white.png');
})
});
</script>
Note that in Firefox it makes two requests, both resulting in 200-OK, and sending the entire image back to the browser twice. In Chromium, it at least correctly gets a 304 on second request instead of downloading the entire contents twice.
Oddly enough, IE11 downloads the entire image twice, while it seems IE9 aggressively caches it and downloads it once.
Ideally I would hope the ajax wouldn't make a second request at all, since it is requesting exactly the same url. Is there a reason css and ajax in this case usually have different caches, as though the browser is using different cache storage for css vs ajax requests?
I use the newest Google Chrome and it makes one request. But in your JSFIDDLE example you are loading jQuery twice. First with CSS over style attribute and second in your code over script tag. Improved: JSFIDDLE
<div id="something" style="background-image:url('http://jsfiddle.net/img/logo-white.png');">Hello</div>
<script>
jQuery(window).load(function() {
jQuery.get('http://jsfiddle.net/img/logo-white.png');
});
// or
jQuery(function($) {
jQuery.get('http://jsfiddle.net/img/logo-white.png');
});
</script>
jQuery(function($) {...} is called when DOM is ready and jQuery(window).load(...); if DOM is ready and every image and other resources are loaded. To put both together nested makes no sense, see also here: window.onload vs $(document).ready()
Sure, the image is loaded two times in Network tab of the web inspector. First through your CSS and second through your JavaScript. The second request is probably cached.
UPDATE: But every request if cached or not is shown in this tab. See following example: http://jsfiddle.net/95mnf9rm/4/
There are 5 request with cached AJAX calls and 5 without caching. And 10 request are shown in 'Network' tab.
When you use your image twice in CSS then it's only requested once. But if you explicitly make a AJAX call then the browser makes an AJAX call. As you want. And then maybe it's cached or not, but it's explicitly requested, isn't it?
This "problem" could a be a CORS pre-flight test.
I had noticed this in my applications awhile back, that the call to retrieve information from a single page application made the call twice. This only happens when you're accessing URLs on a different domain. In my case we have APIs we've built and use on a different server (a different domain) than that of the applications we build. I noticed that when I use a GET or POST in my application to these RESTFUL APIs the call appears to be made twice.
What is happening is something called pre-flight (https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS), an initial request is made to the server to see if the ensuing call is allowed.
Excerpt from MDN:
Unlike simple requests, "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
Your fiddle tries to load a resource from another domain via ajax:
I think I created a better example. Here is the code:
<img src="smiley.png" alt="smiley" />
<div id="respText"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(window).load(function(){
$.get("smiley.png", function(){
$("#respText").text("ajax request succeeded");
});
});
</script>
You can test the page here.
According to Firebug and the chrome network panel the image is returned with the status code 200 and the image for the ajax request is coming from the cache:
Firefox:
Chrome:
So I cannot find any unexpected behavior.
Cache control on Ajax requests have always been a blurred and buggy subject (example).
The problem gets even worse with cross-domain references.
The fiddle link you provided is from jsfiddle.net which is an alias for fiddle.jshell.net. Every code runs inside the fiddle.jshell.net domain, but your code is referencing an image from the alias and browsers will consider it a cross-domain access.
To fix it, you could change both urls to http://fiddle.jshell.net/img/logo-white.png or just /img/logo-white.png.
The helpful folks at Mozilla gave some details as to why this happens. Apparently Firefox assumes an "anonymous" request could be different than normal, and for this reason it makes a second request and doesn't consider the cached value with different headers to be the same request.
https://bugzilla.mozilla.org/show_bug.cgi?id=1075297
This may be a shot in the dark, but here's what I think is happening.
According to,
http://api.jquery.com/jQuery.get/
dataType
Type: String
The type of data expected from the server.
Default: Intelligent Guess (xml, json, script, or html).
Gives you 4 possible return types. There is no datatype of image/gif being returned. Thus, the browser doesn't test it's cache for the src document as it is being delivered a a different mime type.
The server decides what can be cached and for how long. However, it again depends on the browser, whether or not to follow it. Most web browsers like Chrome, Firefox, Safari, Opera and IE follow it, though.
The point that I want to make here, is that your web sever might be configured to not allow your browser to cache the content, thus, when you request the image through CSS and JS, the browser follows your server's orders and doesn't cache it and thus it requests the image twice...
I want JS-accessible image
Have you tried to CSS using jQuery? It is pretty fun - you have full CRUD (Create, read, update, delete) CSS elements. For example do image resize on server side:
$('#container').css('background', 'url(somepage.php?src=image_source.jpg'
+ '&w=' + $("#container").width()
+ '&h=' + $("#container").height() + '&zc=1');
Surprisingly, I found that even when the javascript waits for the entire page to load, the image request still makes a new request! Is this a known bug in Firefox and Chrome, or something bad jQuery ajax is doing?
It is blatantly obvious that this is not a browser bug.
The computer is deterministic and does what exactly you tell it to (not want you want it to do). If you want to cache images it is done in server side. Based on who handles caching it can be handled as:
Server (like IIS or Apache) cache - typically caches things that are reused often (ex: 2ce in 5 seconds)
Server side application cache - typically it reuses server custom cache or you create sprite images or ...
Browser cache - Server side adds cache headers to images and browsers maintain cache
If it is not clear then I would like to make it clear : You don't cache images with javascript.
Ideally I would hope the ajax wouldn't make a second request at all, since it is requesting exactly the same url.
What you try to do is to preload images.
Once an image has been loaded in any way into the browser, it will be
in the browser cache and will load much faster the next time it is
used whether that use is in the current page or in any other page as
long as the image is used before it expires from the browser cache.
So, to precache images, all you have to do is load them into the
browser. If you want to precache a bunch of images, it's probably best
to do it with javascript as it generally won't hold up the page load
when done from javascript. You can do that like this:
function preloadImages(array) {
if (!preloadImages.list) {
preloadImages.list = [];
}
for (var i = 0; i < array.length; i++) {
var img = new Image();
img.onload = function() {
var index = preloadImages.list.indexOf(this);
if (index !== -1) {
// remove this one from the array once it's loaded
// for memory consumption reasons
preloadImages.splice(index, 1);
}
}
preloadImages.list.push(img);
img.src = array[i];
}
}
preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"]);
Then, once they've been preloaded like this via javascript, the browser will have them in its cache and you can just refer to the normal URLs in other places (in your web pages) and the browser will fetch that URL from its cache rather than over the network.
Source : How do you cache an image in Javascript
Is there a reason css and ajax in this case usually have different caches, as though the browser is using different cache storage for css vs ajax requests?
Even in absence of information do not jump to conclusions!
One big reason to use image preloading is if you want to use an image
for the background-image of an element on a mouseOver or :hover event.
If you only apply that background-image in the CSS for the :hover
state, that image will not load until the first :hover event and thus
there will be a short annoying delay between the mouse going over that
area and the image actually showing up.
Technique #1 Load the image on the element's regular state, only shift it away with background position. Then move the background
position to display it on hover.
#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }
Technique #2 If the element in question already has a background-image applied and you need to change that image, the above
won't work. Typically you would go for a sprite here (a combined
background image) and just shift the background position. But if that
isn't possible, try this. Apply the background image to another page
element that is already in use, but doesn't have a background image.
#random-unsuspecting-element {
background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }
The idea create new page elements to use for this preloading technique
may pop into your head, like #preload-001, #preload-002, but that's
rather against the spirit of web standards. Hence the using of page
elements that already exist on your page.
The browser will make the 2 requests on the page, cause an image called from the css uses a get request (not ajax) too before rendering the entire page.
The window load is similar to de attribute, and is loading before the rest of the page, then, the image from the Ajax will be requested first than the image on the div, processed during the page load.
If u would like to load a image after the entire page is loaded, u should use the document.ready() instead

Categories

Resources