'Javascript Human Readable Filesize

I am currently trying to convert this php function to javascript:

function human_filesize($bytes, $decimals = 2) {
  $sz = 'BKMGTP';
  $factor = floor((strlen($bytes) - 1) / 3);
  return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}

Here's what I have so Far:

function human_filesiz(bytes){
            var decimals = 2;
            var sz = 'BKMGTP';
            var factor = Math.floor((bytes.length - 1) / 3);
            return (bytes / Math.pow(1024, factor));
            //return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
        }

Im Just struggling with the last line. Any Help Greatly Appreciated.



Solution 1:[1]

Based on the new international standards:

there are 2 ways now (SI & IEC)... or better 3 including the old one(JEDEC memory standards).


old standard (JEDEC & SI):

kB=1000, KB=1024

MB=1024=1000

GB=1024=1000

as you can see everything is messed up as you don't know if they are using 1024 or 1000 as multipler

https://wiki.ubuntu.com/UnitsPolicy


thats why we have this 2 new standards now:

Decimal (International System of Units [SI])

kB,MB,GB.. = 1000

Binary (International Electrotechnical Commission [IEC])

KiB,MiB,GiB.. = 1024

http://en.wikipedia.org/wiki/Binary_prefix

here are 2 functions i just wrote using shorthand and bitwise to make it fast & short.

function fileSizeSI(a,b,c,d,e){
 return (b=Math,c=b.log,d=1000,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
 +' '+(e?'kMGTPEZY'[--e]+'B':'Bytes')
}
//kB,MB,GB,TB,PB,EB,ZB,YB

function fileSizeIEC(a,b,c,d,e){
 return (b=Math,c=b.log,d=1024,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
 +' '+(e?'KMGTPEZY'[--e]+'iB':'Bytes')
}
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB

usage

fileSizeSI(5768374623);
//5.77 GB

fileSizeIEC(5768374623);
//5.37 GiB

EDIT

And here is a prototype for modern browsers that can handle both

Object.defineProperty(Number.prototype,'fileSize',{value:function(a,b,c,d){
 return (a=a=='SI'?[1e3,'k','B']:[1024,'K','iB'],b=Math,c=b.log,
 d=c(this)/c(a[0])|0,this/b.pow(a[0],d)).toFixed(2)
 +' '+(d?(a[1]+'MGTPEZY')[--d]+a[2]:'Bytes');
},writable:false,enumerable:false});
// default(IEC) KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
// (SI) kB,MB,GB,TB,PB,EB,ZB,YB

usage

(1289139173).fileSize(); // default Binary IEC
//1.20 GiB

(1289139173).fileSize('SI'); // Metric SI
//1.29 GB 

i always used 1024 to calculate the size ... so i put the new IEC standard as default.

if you have some questions about the functions just ask

Solution 2:[2]

we should stop the loop when size exceeds what we have anticipated in the units array

function toHuman(size) {
    var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];  
    var i = 0;  
    var j = units.length - 1; 
    while(size >= 1024 && i<j) {  
        size /= 1024;  
        ++i;  
    }  
    return size.toFixed(1) + ' ' + units[i];  
}  

Solution 3:[3]

The answer by osi is great. If you want to understand what JS can do for your example though, you can take a look at this code which I made work for you:

function human_filesiz(bytes){
    var decimals = 2;
    var sz = 'BKMGTP';
    bytesStr = new String(bytes);
    var factor = Math.floor((bytesStr.length - 1) / 3);

    // rounding the number in JS:
    var number = bytes / Math.pow(1024, factor);
    var roundPrecision = Math.pow(10, decimals);
    number *= roundPrecision;
    var result = Math.round(number, decimals) / roundPrecision;
    result = result + sz.substring(factor, 1);
    return result;
}

JsFiddle

Solution 4:[4]

I like cocco's version.

I added rounding and locale conversion for the separators.

Object.defineProperty(Number.prototype, 'toFileSize', {
value: function(a, b, c, d){ return (a=a=='SI'?[1e3,'k','B']:[1024,'K','iB'],b=Math,c=b.log,d=c(this)/c(a[0])|0,+(b.round(this/b.pow(a[0],d)+"e+2")+"e-2")).toLocaleString()+' '+(d?(a[1]+'MGTPEZY')[--d]+a[2]:'Bytes');},
writable: false,
enumerable: false
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Community
Solution 4 Community