Convert size in bytes to human readable format (JavaScript)

This is JavaScript implementation of the function described in my earlier article Convert size in bytes to a human readable format (PHP). Please see the link for more in-depth explanation of the function workflow.

  1. /**
  2.  * Convert number of bytes into human readable format
  3.  *
  4.  * @param integer bytes     Number of bytes to convert
  5.  * @param integer precision Number of digits after the decimal separator
  6.  * @return string
  7.  */
  8. function bytesToSize(bytes, precision)
  9. {  
  10.     var kilobyte = 1024;
  11.     var megabyte = kilobyte * 1024;
  12.     var gigabyte = megabyte * 1024;
  13.     var terabyte = gigabyte * 1024;
  14.    
  15.     if ((bytes >= 0) && (bytes < kilobyte)) {
  16.         return bytes + ' B';
  17.  
  18.     } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
  19.         return (bytes / kilobyte).toFixed(precision) + ' KB';
  20.  
  21.     } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
  22.         return (bytes / megabyte).toFixed(precision) + ' MB';
  23.  
  24.     } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
  25.         return (bytes / gigabyte).toFixed(precision) + ' GB';
  26.  
  27.     } else if (bytes >= terabyte) {
  28.         return (bytes / terabyte).toFixed(precision) + ' TB';
  29.  
  30.     } else {
  31.         return bytes + ' B';
  32.     }
  33. }

Comments
1
It's not really optimistic, personally I use this, translated from a PHP function in the documentation :
function bytesToSize(bytes) {
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    if (bytes == 0) return 'n/a';
    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
    return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
};
ThomasR, August 24th 2010, 14:01
2
@ThomasR, this is really great logic.
Anon, October 21st 2010, 16:58
3
There is a bug in ThomasR's code...

The last line should be " + sizes[i];"

function bytesToSize(bytes) {
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    if (bytes == 0) return 'n/a';
    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
    return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
};
Ben Timby, January 29th 2011, 0:27
4
I see what happened now, the stupid comment box filters square brackets. Let me see if I can escape them...

--
There is a bug in ThomasR's code...

The last line should be " + sizes[[i]];"

function bytesToSize(bytes) {
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    if (bytes == 0) return 'n/a';
    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
    return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[[i]];
};

--
Ben Timby, January 29th 2011, 0:28
5
BAH, oh well, there should be an i in between the square brackets so that the correct denomination is used, instead of all of them.
Ben Timby, January 29th 2011, 0:29
6
The issue was that you were using i inside the square brackets and that was supposed to be the "bbcode" for italic. As a temporary fix I removed support for that tag as no one's using it anyway. I need to make sure that I am not replacing bold, italic, etc. inside the code tags.

Sorry for inconvenience caused :)

Speaking about Ben's example. I do agree that it's a nice solution as well. Thanks for the input!
Andris, February 7th 2011, 11:42
7
If you want a decimal instead of rounding.
Replace Math.Round with .toFixed();

function bytesToSize(bytes) {
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    if (bytes == 0) return 'n/a';
    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
    return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
};
Jonathan, June 5th 2011, 16:35
8
We could extend the units to cover more units.
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

We could also use SI binary prefixes instead of SI decimal prefixed.
    var sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
Jonathan, June 5th 2011, 16:44
9
The above function I wrote will print '8.0 bytes', you probably want that to be just '8 bytes'.

function bytesToSize(bytes) {
  var sizes = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
  if (bytes == 0) return 'n/a';
  var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  if (i == 0) { return (bytes / Math.pow(1024, i)) + ' ' + sizes[i]; }
  return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
}
Jonathan, June 5th 2011, 16:46
10
I like your solution, Jonathan. Looking back at the code I realize that it's not the shortest way of doing it but I guess we all see our flaws when we revisit the code we've written some time ago :)

But, nevertheless, thanks for your contribution! Much appreciated!
Andris, June 9th 2011, 20:53
11
Ok my turn... compressing the work of Jonathan a bit more we end up with the following:

function bytesToSize (bytes) {
  var sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
  if (bytes == 0) return 'n/a';
  var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  return ((i == 0)? (bytes / Math.pow(1024, i)) : (bytes / Math.pow(1024, i)).toFixed(1)) + ' ' + sizes[i];
};
Fergus, June 15th 2011, 12:14
12
Here's a simplified version of the Jonathan's method.

function bytesToSize2(bytes) {
    var sizes = [ 'n/a', 'bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
    var i = +Math.floor(Math.log(bytes) / Math.log(1024));
    return  (bytes / Math.pow(1024, i)).toFixed( i ? 1 : 0 ) + ' ' + sizes[ isNaN( bytes ) ? 0 : i+1 ];
}


Here's my version of the same thing so.
Code of the day: Javascript convert bytes to KB, MB, GB, etc | Learning is bateru
Larry Battle, November 28th 2011, 21:21
13
No offense guys but the floor/round/pow,... shizzle seems a lil over the top for such a function. It results in an "incorrect" space shown by all the rounds.
Furthermore parseInt... Really? :p There is no need for that. Just wrote this function in a minute and I would think it would give more decent result and the calculation time should be alot shorter.

function bytesToSize(bytes, precision) {
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    var posttxt = 0;
    if (bytes == 0) return 'n/a';
    while( bytes >= 1024 ) { 
        posttxt++;
        bytes = bytes / 1024;
    }   
    return bytes.toFixed(precision) + " " + sizes[posttxt];
}

Hopes this helps someone else!
me me me, January 1st 2012, 22:15
14
me me me, yes parseInt.  When I pass in a value < 1024, it's a string and .toFixed throws an error "bytes.toFixed is not a function".  Your function is fixed with either
return parseInt(bytes).toFixed...
or by adding at the top
bytes = bytes * 1;
Israel, March 8th 2012, 21:56
Name
Email (required)
will not be published
Website
Recaptcha
you will only be required to fill it in once in this session

You can use [code][/code] tags in your comments