6

Good evening,

I'm using a material-ui Card inside a React functional component, with a CardMedia such as :

<CardMedia
  className={classes.media}
  image={props.image}
  title={props.cardTitle}
/>

I'm trying to determine the image file size in bytes. After some research I found solutions which use XMLHttpRequest. It seems strange to me to download the file again. I found how to get the image width and height using :

function checkImage() {
    var img = new Image();
    img.addEventListener("load", function(){
        console.log( this.naturalWidth +' '+ this.naturalHeight );
    });
    img.src = props.image;
}

It works, but this is not what I'm looking for and if I'm not mistaken this downloads the image again. I looked into Mozilla doc, Image only has width and height properties. Since the image is already loaded, I should have a way to determine its size in byte without using XMLHttpRequest ?

Jean Coiron
  • 632
  • 8
  • 24

1 Answers1

4

#1: You can fetch the Content-Length header of a resource with a HEAD request like so:

fetch('https://your-domain/your-resource', { method: 'HEAD' })
  .then(r => console.log('size:', r.headers.get('Content-Length'), 'bytes'));

This way only the headers are downloaded, nothing more.

#2: Alternatively you can use the Resource Timing API:

const res = performance.getEntriesByName('https://your-domain/your-resource');
console.log(res[0].transferSize, res[0].encodedBodySize, res[0].decodedBodySize);

Just be aware that the resource needs to be on the same subdomain, otherwise you'll have to add a Timing-Allow-Origin CORS header.

#3: Yet another alternative is to download the image as a blob:

fetch('https://your-domain/your-resource')
  .then(r => r.blob())
  .then(b => console.log(b.size, URL.createObjectURL(b)));

This would of course re-download the image if called after the initial load, but you can use the object URL to reference your image if using this method to load it initially.

Markus Dresch
  • 5,290
  • 3
  • 20
  • 40
  • Is the performance approach works for cached images / resources? – Mosh Feu Oct 22 '20 at 09:50
  • @MoshFeu according to my tests in Chrome and Firefox it does work with cached images. one thing to note is, that the exact absolute URL has to be used. also, if testing a SVG url with a reference (#ref), the ref has to be included. – Markus Dresch Oct 22 '20 at 09:58
  • I'm testing fetching the header, and it seems to work fine. Though I don't understand why there is apparently no way to get this info without doing a new external request. The image is already downloaded and loaded into the page, why can't I access its properties, like its size ? – Jean Coiron Oct 23 '20 at 08:00
  • i guess there are not enough use cases for that, since you can get the information when loading anyway (headers or blob size). #2 is not making another request. – Markus Dresch Oct 23 '20 at 08:07
  • Thanks Markus, I can get the image info without downloading it. #1 does not always works, sometimes I don't see a Content-Length exposed in the header. Due to CORS policies I can't use #2, so in these cases I have to download the image again as a blob. – Jean Coiron Oct 28 '20 at 11:30