简体   繁体   中英

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.

Did you have a look at: http://programanddesign.com/js/human-readable-file-size-in-javascript/ They have two version of a Javascript solution for Human Readable Filesize:

function fileSize(size) {
    var i = Math.floor(Math.log(size) / Math.log(1024));
    return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
}

and

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

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

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

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
});

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];  
}  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM