Download of brotli compressed file: Chrome vs Firefox - google-chrome

Imagine this simple snippet that fetches a file:
const xhr = new XMLHttpRequest()
xhr.onprogress = event => {
console.log(`Progress: ${event.loaded}/${event.total}`)
}
xhr.open('GET', 'https://example.com/myfile.data.br')
xhr.send()
The file is brotli compressed, and served with the following response headers:
content-encoding: br
content-length: 13934674
According to the network tab, 13.94 MB gets transfered when fetching this file, and the resource size is 30.30 MB.
This is what Firefox' console looks like:
As you can see, it's respects the content-length, and is actually able to report progress on it.
This is what Chrome's console looks like:
Notice how both the event.loaded and event.total is different. Chrome seems to report progress on the actually resource size (not the compressed size!), but it doesn't know the total resource size (which makes sense because it's compressed so it doesn't know what the total resource size will be).
When digging a bit deeper, I actually noticed Chrome is just wrong here. It tells you it downloaded 30.30 MB, but it didn't, it only transferred 13.94 MB.
Even when you fetch this file directly via the browser, it looks like Chrome is fooling you (throttled my network to be able to capture it):
See how it's pretending to be downloading 30.30 MB (it's currently at 21.2 MB), while it's actually only downloading 13.94 MB. My download speed is then calculated based on that uncompressed resource size and the elapsed time, and therefor completely wrong. The blue progress bar is actually not a left-to-right progress bar but rather an animated "I don't know the total" progress bar, I just took my screenshot on this particular moment where it appears to be loaded from left to right, but it's not.
Firefox seems to do it better:
Here, we do have a total, and thus a left-to-right progress bar, and the correct download speed.
My questions:
Is this behavior in Chrome expected?
How to properly implement a progress bar that will work for both?

Related

slow download speed with rendered html

My page request content data after html loaded, it take 2 second for completed show page.
When i set all data in one html(server side rendering) and size 485KB,
it take 4 second to show the page.
Why a 485KB size html load time slow than a 1.6MB json?
My server:
a self-host console server.
Owin & RazorEngine for html pages,
WebAPI for json data.
My 2 web page:
1.
html, just static file,
use ajax(WebAPI) request json data.
2.
Set all data in html, server side rendering.
--07/27 18:21 edit
*old title: Why small index html slow than a big json
I do some more test:
*All contents finally are all same.
1. html + webapi request content.
2. html + render content at server.
3. html with content,render nothing.
4. use webapi get html with content no gzip.
5. just for compare, stackoverflow has more waiting time, less download time.This is what i want.
Looks like the problem is RazorEngine.
Rendered html download speed slower than static file.
How do i fix this?
--07/28 10:38 edit
Just find out what problem is.
It's not RazorEngine's problem,the problem is gzip.
Some big html(977KB) use gzip(69KB) download speed faster(1.95s) than raw html(7.80s),
but sometimes gziped html download speed slower than raw html (third img).
I set file size over 100kb to use gzip, but download speed still not stable.
Is there other problem i not found?
Because when HTML is loaded, it also needs time for rendering on the browser depending upon the content. Thus, the time taken is more.

Chrome sends two requests when downloading a PDF (and cancels one of them)

I noticed that whenever you download a PDF in Chrome, it consistently makes two requests, and then cancels one of them. This is causing the request to be registered twice in my Web app, which don't want. Is there a way to get Chrome to only make one request for PDFs?
I've researched this topic quite a bit now, and I have not found a sufficient answer. Closely-related answers suggest that the problem is that Chrome is looking for a favicon, but the network tab shows that it is actually making the same request twice, and then canceling the second request.
Is there a way to prevent Chrome from making the second request?
Below is a link to a random PDF file that I found through Google which when clicked should demonstrates the behavior. I would've posted a picture of my network tab in devtools but this is my first post on Stack Overflow, and the site is prohibiting me from uploading a picture.
https://www.adobe.com/enterprise/accessibility/pdfs/acro6_pg_ue.pdf
It looks like a bug in Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=587709
The problem is that Chrome, when it loads an iframe that returns a PDF stream, writes an "embed" tag inside that iframe which again contains the same URL as the iframe. This triggers a request for that URL again, but Chrome immediately cancels it. (see the network tab)
But by that time, the damage is done.
We have the same issue here, and it does not occur in Firefox or IE.
We're still looking for a good solution to this problem.
I'm still trying to find a proper solution but as a partial "fix" for now you could have two options
1) set the content disposition to "attachment" in the header
setting that to "inline" cause chrome to run a second cancelled call
so for example you can do something like that (nodejs resp in example)
res.writeHead(200, {
'Content-Type' : 'application/pdf',
'Access-Control-Allow-Origin' : '*',
'Content-Disposition' : 'attachment; filename=print.pdf'
});
unfortunately this solution will force the browser to download the pdf straight away instead of rendering it inline and that's not maybe desiderable
2) adding "expires" in the headers
this solution will always fire a second cancelled call but it's ignored by the server
so for example you can do something like that (nodejs resp in example)
res.writeHead(200, {
'Content-Type' : 'application/pdf',
'Access-Control-Allow-Origin' : '*',
'Content-Disposition' : 'inline; filename=print.pdf',
'Expires' : new Date(new Date().getTime() + (60000))
});
I had the same problem in an iframe. I turned of the PDF Viewer extension and the problem disappeared. I'm thinking the extension downloads the file twice. The first time to get the size, the second time to download with a progress bar (using the size gathered in the first request)
I've tried the other solutions and none worked for me, I'm a little late, I know, but just for the record, I solved this in the following manner:
Adding the download attribute:
In my case I was using a form, so it goes like this:
<form action="/package.zip" method="POST" download>
This worked on Brave and Safari, which previously showed the same problem, I think it will work for Chrome.
With my case, problem wasn't browser related. I've noticed our scrollbar plugin's (OverlayScrollbars) DOM manipulations reloads embedded pdf data and calls controller more than once due to on plugin's construct or destroy events. After I've initialized scrollbar before DOM is ready, problem is solved.

NSURLSession is not downloading full webpage

I'm currently attempting to download a webpage using a NSURLSession in order to retrieve a status update on the download progress. Unfortunately, after downloading the webpage, when I go to load the webpage, there are visual issues (missing images, missing javascript, missing styles, etc), leaving the webpage looking broken and in complete. When loading directly to the webView, everything loads correctly. I would like to know if there is a way (or anything I'm missing) to download ALL aspects of the webpage and load them up so I may load the full webpage and display a loading bar while the page loads.
- (void)loadRequest:(NSURLRequest *)request
{
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
self.urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
self.downloadTask = [self.urlSession downloadTaskWithRequest:request];
[self.downloadTask resume];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL
{
[_webView loadData:[NSData dataWithContentsOfURL:downloadURL] MIMEType:downloadTask.response.MIMEType textEncodingName:downloadTask.response.textEncodingName baseURL:nil];
}
I was having similar problems (missing images etc.). You need to provide a baseURL. Try:
[_webView loadData:[NSData dataWithContentsOfURL:downloadURL] MIMEType:downloadTask.response.MIMEType textEncodingName:downloadTask.response.textEncodingName baseURL:downloadTask.response.URL];
In order to display a loading bar you have to make some kind of workaround, because you are not able to know the progress of the resources that are being downloaded.
Many apps use tricks, to simulate that there is a loading ongoing.
Here is a simple example to ilustrate the idea:
Display loading bar with progress 30% for 1 second.
If the request did not finish, display progress 90% until the progress finishes
When the request finishes, animate progress to 100%.
You can have a look on this open source library to see how it's done. You can do it in a similar way.
https://github.com/ninjinkun/NJKWebViewProgress

Invalid PNG Image file: iDOT doesn't point to valid IDAT chunk

I have some HTML content pages in an app and I'm using a UIWebView to display them. Some of these pages have a PNG image in them that is generating the following message in the debug console in xcode:
ImageIO: PNG invalid PNG file: iDOT doesn't point to valid IDAT chunk
The image still displays and looks correct. Also this only happens when I run the app on an iPad (3rd generation). My iPhone 4 doesn't display this message.
My first thought was that it was caused by a ~ character in the filename (I've added the ~ipad tag to the filename). However, removing the ~ character doesn't have any effect.
I've done a google search but I only get 3 results. 2 of them are in Chinese that doesn't seem to be translated well by Google's translater. The other results seems to be someone with the same issue as me, but no responses to his post.
Had the same problem. Solution:
use "color sync utility" which is a standard program, you can load from launchpad. Open the png file and save it with the utility.
'cleaning' the project (xcode menu path : product -> clean) solved this exact issue for me.
Resaving the .png with a new name did not.
Image did appear in the simulator but not on the test device (ipod touch 5th gen.)
Very large image 4000 x 4000
Strangely, I had the exact same issue just about an hour ago. I didn't find a particular reason for why it was failing, but I think I was able to "fix" the image to make it display properly and not throw an error.
I just opened it in Preview and exported a new PNG file from the source. Once I replaced the bad image in my project file with the newly created one, I cleaned, compiled and it worked as expected.
Hope it's as easy as that for you...
You may want to check you don't have another file with the same name in another directory. That is what caused this error for me .. (duplicate Default.png)
I had the same problem with my app.It turn out that the images that the user was uploading to my server and edited with php +imagemagik where striped out.I was using the following command to edit the uploaded image:
convert $uploadfile -resize 300x300 -quality 30 -strip $uploadfile
When i removed the -strip parameter the error was disappeared !
Same problem here.
1 - Close XCode;
2 - Open the image in Photoshop;
3 - Re-save ( replace the same image ) with 80% quality;
4 - Open XCode, clean it CMD + SHIFT + K;
5 - Build it in your device again;
Very simple and work for me.
And for you ?

Chrome Dev Tools - "Size" vs "Content"

When viewing information about stylesheets in the Network tab of Chrome's dev tools, one column specifies both "size" and "content":
Can anybody shed light on the difference between these two numbers? On some pages the numbers are close and others they are different by a considerable amount.
"Size" is the number of bytes on the wire, and "content" is the actual size of the resource. A number of things can make them different, including:
Being served from cache (small or 0 "size")
Response headers, including cookies (larger "size" than "content")
Redirects or authentication requests
gzip compression (smaller "size" than "content", usually)
From the docs:
Size is the combined size of the response headers (usually a few
hundred bytes) plus the response body, as delivered by the server.
Content is the size of the resource's decoded content. If the resource
was loaded from the browser's cache rather than over the network, this
field will contain the text (from cache).
Size is the size of response itself, and Content is the size of resource, that you are accessing.
Compare:
empty cache:
main.js GET 200 OK .. Size: 31.72KB Content: 31.42KB
cached:
main.js GET 304 Not modified .. Size: 146B Content: 31.42KB
In simple terms Google article explain it as
Size = Transfer size and Content = Actual size
This is my formula based on reading various articles on this topic (and I am open to improve it further with your comments)
Size = Compression(Content) + Response Header
See the image used in this article
Explanation by Google
"Use large request rows" to show both values!
If you don't see the second value (content) you need to click the "Use large request rows" button inside Chrome Network tab:
I found this thanks to the answer on this question here:
Chrome Devs tools - where's size and content?
Size includes response AND request info
Size is a sum of:
bytes transferred for the request header
bytes transferred for the response header
bytes transferred for the response body
From the docs:
Inspecting the properties of an individual resource, such as its HTTP headers [note the plural, emphasis mine], content, size, and so on.
If you compare the transferSize of a performanceEntry (e.g. for the main document at https://stackoverflow.com/) with the Size in Chrome DevTools' Network tab, you'll see that the two don't match up. That is because the performanceEntry doesn't contain the size of the request header.
Screenshot of the Network tab and a logged performance entry