504

I got this code to covert size in bytes via PHP.

Now I want to convert those sizes to human readable sizes using JavaScript. I tried to convert this code to JavaScript, which looks like this:

function formatSizeUnits(bytes){
  if      (bytes >= 1073741824) { bytes = (bytes / 1073741824).toFixed(2) + " GB"; }
  else if (bytes >= 1048576)    { bytes = (bytes / 1048576).toFixed(2) + " MB"; }
  else if (bytes >= 1024)       { bytes = (bytes / 1024).toFixed(2) + " KB"; }
  else if (bytes > 1)           { bytes = bytes + " bytes"; }
  else if (bytes == 1)          { bytes = bytes + " byte"; }
  else                          { bytes = "0 bytes"; }
  return bytes;
}

Is this the correct way of doing this? Is there an easier way?

1
  • 8
    This actually converts to GiB, MiB, and KiB. This is standard for file sizes, but not always for device sizes. Commented Apr 9, 2013 at 11:40

35 Answers 35

1349

From this: (source)


Unminified and ES6'ed: (by the community)

function formatBytes(bytes, decimals = 2) {
    if (!+bytes) return '0 Bytes'

    const k = 1024
    const dm = decimals < 0 ? 0 : decimals
    const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']

    const i = Math.floor(Math.log(bytes) / Math.log(k))

    return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}

// Demo code
document.body.innerHTML += `<input type="text" oninput="document.querySelector('p').innerHTML=formatBytes(this.value)" value="1000"><p>1000 Bytes</p>`

Minified version (by StackOverflow's community, minified by JSCompress)

function formatBytes(a,b=2){if(!+a)return"0 Bytes";const c=0>b?0:b,d=Math.floor(Math.log(a)/Math.log(1024));return`${parseFloat((a/Math.pow(1024,d)).toFixed(c))} ${["Bytes","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"][d]}`}

Usage:

// formatBytes(bytes, decimals)

formatBytes(1024)       // 1 KiB
formatBytes('1024')     // 1 KiB
formatBytes(1234)       // 1.21 KiB
formatBytes(1234, 3)    // 1.205 KiB
formatBytes(0)          // 0 Bytes
formatBytes('0')        // 0 Bytes

PS : Change k = 1000 or sizes = ["..."] as you want (bits or bytes)

Sign up to request clarification or add additional context in comments.

22 Comments

(1) why bytes = 0 is "n/a"? Isn't it just "0 B"? (2) Math.round doesn't have precision parameter. I'd better use (bytes / Math.pow(1024, i)).toPrecision(3)
toFixed(n) is probably more appropriate than toPrecision(n) to have a consistant precision for all the values. And to avoid trailing zeros (ex: bytesToSize(1000) // return "1.00 KB") we could use parseFloat(x). I suggest to replace the last line by: return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];. With the previous change the results are: bytesToSize(1000) // return "1 KB" / bytesToSize(1100) // return "1.1 KB" / bytesToSize(1110) // return "1.11 KB / bytesToSize(1111) // also return "1.11 KB"
I believe plural form is used for 0: '0 Bytes'
KB = Kelvin bytes in SI units. which is nonsensical. It should be kB.
To be precise, if k is 1024 then the unit abbreviations should be KiB, MiB, GiB, etc. These are kibibytes, mebibytes, gibibytes, etc.
|
89

This solution includes a decimal point and a tenths-place digit if presenting less than ten of KB or greater units

const units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
   
function niceBytes(x){

  let l = 0, n = parseInt(x, 10) || 0;

  while(n >= 1024 && ++l){
      n = n/1024;
  }
  
  return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]);
}

Results:

niceBytes(7)                   // 7 bytes
niceBytes(435)                 // 435 bytes
niceBytes(3398)                // 3.3 KiB
niceBytes(490398)              // 479 KiB
niceBytes(6544528)             // 6.2 MiB
niceBytes(23483023)            // 22 MiB
niceBytes(3984578493)          // 3.7 GiB
niceBytes(30498505889)         // 28 GiB
niceBytes(9485039485039445)    // 8.4 PiB

Note: Use the "Kib", etc. abbreviations when using base 1024, because "KB", etc. actually refers to base 1000. If you wish to calculate the value to base 1000, then just replace 1024 with 1000 in this function, and use the appropriate units (kB, MB, etc.)

3 Comments

Thanks! Compressed: function niceBytes(a){let b=0,c=parseInt(a,10)||0;for(;1024<=c&&++b;)c/=1024;return c.toFixed(10>c&&0<b?1:0)+" "+["bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][b]}
as written elsewhere, 1MB=1000KB, not 1024. See en.wikipedia.org/wiki/Megabyte
@Iacopo: updated to address KiB, etc, rather than kB, as that seems to have been the OP's intent.
54
function formatBytes(bytes) {
    var marker = 1024; // Change to 1000 if required
    var decimal = 3; // Change as required
    var kiloBytes = marker; // One Kilobyte is 1024 bytes
    var megaBytes = marker * marker; // One MB is 1024 KB
    var gigaBytes = marker * marker * marker; // One GB is 1024 MB
  
    // return bytes if less than a KB
    if(bytes < kiloBytes) return bytes + " Bytes";
    // return KB if less than a MB
    else if(bytes < megaBytes) return(bytes / kiloBytes).toFixed(decimal) + " KB";
    // return MB if less than a GB
    else if(bytes < gigaBytes) return(bytes / megaBytes).toFixed(decimal) + " MB";
    // return GB if less than a TB
    else return(bytes / gigaBytes).toFixed(decimal) + " GB";
}

2 Comments

I did a fiddle base on ur code : jsfiddle.net/darkkyoun/3g71k6ho/16 Hope it will help someone
does not use terabytes?
45

Here's a one liner:

val => ['Bytes','Kb','Mb','Gb','Tb'][Math.floor(Math.log2(val)/10)]

Or even:

v => 'BKMGT'[~~(Math.log2(v)/10)]

With count:

function shortenBytes(n) {
    const k = n > 0 ? Math.floor((Math.log2(n)/10)) : 0;
    const rank = (k > 0 ? 'KMGT'[k - 1] : '') + 'b';
    const count = Math.floor(n / Math.pow(1024, k));
    return count + rank;
}

4 Comments

Nice !, But if 1k is 1024 not 1000 ?
This calculation is treating 1k as 2^10, 1m as 2^20 and so on. if you want 1k to be 1000 you can change it a bit to use log10.
Here's a version that treats 1K as 1000: val => 'BKMGT'[~~(Math.log10(val)/3)]
This is nice! I expanded on this to return the full string I wanted from my function: i = ~~(Math.log2(b)/10); return (b/Math.pow(1024,i)).toFixed(2) + ("KMGTPEZY"[i-1]||"") + "B"
18

There are 2 real ways to represent sizes when related to bytes, they are SI units (10^3) or IEC units (2^10). There is also JEDEC but their method is ambiguous and confusing. I noticed the other examples have errors such as using KB instead of kB to represent a kilobyte so I decided to write a function that will solve each of these cases using the range of currently accepted units of measure.

There is a formatting bit at the end that will make the number look a bit better (at least to my eye) feel free to remove that formatting if it doesn't suit your purpose.

Enjoy.

// pBytes: the size in bytes to be converted.
// pUnits: 'si'|'iec' si units means the order of magnitude is 10^3, iec uses 2^10

function prettyNumber(pBytes, pUnits) {
    // Handle some special cases
    if(pBytes == 0) return '0 Bytes';
    if(pBytes == 1) return '1 Byte';
    if(pBytes == -1) return '-1 Byte';

    var bytes = Math.abs(pBytes)
    if(pUnits && pUnits.toLowerCase() && pUnits.toLowerCase() == 'si') {
        // SI units use the Metric representation based on 10^3 as a order of magnitude
        var orderOfMagnitude = Math.pow(10, 3);
        var abbreviations = ['Bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    } else {
        // IEC units use 2^10 as an order of magnitude
        var orderOfMagnitude = Math.pow(2, 10);
        var abbreviations = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
    }
    var i = Math.floor(Math.log(bytes) / Math.log(orderOfMagnitude));
    var result = (bytes / Math.pow(orderOfMagnitude, i));

    // This will get the sign right
    if(pBytes < 0) {
        result *= -1;
    }

    // This bit here is purely for show. it drops the percision on numbers greater than 100 before the units.
    // it also always shows the full number of bytes if bytes is the unit.
    if(result >= 99.995 || i==0) {
        return result.toFixed(0) + ' ' + abbreviations[i];
    } else {
        return result.toFixed(2) + ' ' + abbreviations[i];
    }
}

Comments

15

You can use the filesizejs library.

4 Comments

I guess this library gives the accurate representation, since 1024 bytes is 1 KB, not 1000 bytes (as provided by some other solutions here). Thanks @maurocchi
@W.M. that statement is not true. 1kB = 1000 bytes. There are 1024 bytes in a Kibibyte. There has been confusion in the past so these two terms precisely explain the difference in size.
@BrennanT It depends how old you are. 1KB used to be 1024 bytes and most people over a certain age still see it as such.
for people who come here for a lib, here is better one: npmjs.com/package/pretty-bytes
10

Just slightly modified the code of @zayarTun answer to include an extra parameter representing the number of decimals in the result (also if the decimals are zero then no need to show a result like 15.00 KB, instead 15 KB is sufficient, that's why I wrapped the result value in parseFloat())

  bytesForHuman(bytes, decimals = 2) {
    let units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']

    let i = 0
    
    for (i; bytes > 1024; i++) {
        bytes /= 1024;
    }

    return parseFloat(bytes.toFixed(decimals)) + ' ' + units[i]
  }

Comments

8

Utility method to format bytes into the most logical magnitude (KB, MB, or GB)

Number.prototype.formatBytes = function() {
    var units = ['B', 'KB', 'MB', 'GB', 'TB'],
        bytes = this,
        i;
 
    for (i = 0; bytes >= 1024 && i < 4; i++) {
        bytes /= 1024;
    }
 
    return bytes.toFixed(2) + units[i];
}

let a = 235678; //bytes

console.log(a.formatBytes()); //result is 230.15KB

Comments

7

Using bitwise operation would be a better solution. Try this

function formatSizeUnits(bytes)
{
    if ( ( bytes >> 30 ) & 0x3FF )
        bytes = ( bytes >>> 30 ) + '.' + ( bytes & (3*0x3FF )) + 'GB' ;
    else if ( ( bytes >> 20 ) & 0x3FF )
        bytes = ( bytes >>> 20 ) + '.' + ( bytes & (2*0x3FF ) ) + 'MB' ;
    else if ( ( bytes >> 10 ) & 0x3FF )
        bytes = ( bytes >>> 10 ) + '.' + ( bytes & (0x3FF ) ) + 'KB' ;
    else if ( ( bytes >> 1 ) & 0x3FF )
        bytes = ( bytes >>> 1 ) + 'Bytes' ;
    else
        bytes = bytes + 'Byte' ;
    return bytes ;
}

12 Comments

Obtain the remaining bytes. That will provide the decimal portion.
Its 1024. If you require 100 shift the bits accordingly.
Please do not grab code from the internet without understanding it or at least testing it. This is a good example of code that is simply wrong. Try running it by passing it 3 (returns "1Bytes") or 400000.
Dear Amir Haghighat, this is a basic code solely written by me. In javasript post 32 bits of integer value the code will not work since integer is only four bytes. These are basic programming infos that you should be knowing. Stackoverflow is meant only for guiding people and not spoon feeding.
|
6

This works for me.

bytesForHuman(bytes) {
    let units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']

    let i = 0
    
    for (i; bytes > 1024; i++) {
        bytes /= 1024;
    }

    return bytes.toFixed(1) + ' ' + units[i]
}

1 Comment

A bit cleaner imo: const units = ["B", "KB", "MB", "GB"]; while (bytes > 1024 && units.length) { bytes /= 1024; units.shift(); } return bytes.toFixed(1) + " " + units[0];
6

This is not about converting bytes to other units, but it helps to correctly display the number and the unit for the current locale:

bytes.toLocaleString(undefined, {
  style: 'unit',
  unit: 'gigabyte',
})

More options and details can be found here: https://v8.dev/features/intl-numberformat#units

Comments

4

According to Aliceljm's answer, I removed 0 after decimal:

function formatBytes(bytes, decimals) {
    if(bytes== 0)
    {
        return "0 Byte";
    }
    var k = 1024; //Or 1 kilo = 1000
    var sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
    var i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + " " + sizes[i];
}

Comments

4

function bytesToSize(bytes) {
  var sizes = ['B', 'K', 'M', 'G', 'T', 'P'];
  for (var i = 0; i < sizes.length; i++) {
    if (bytes <= 1024) {
      return bytes + ' ' + sizes[i];
    } else {
      bytes = parseFloat(bytes / 1024).toFixed(2)
    }
  }
  return bytes + ' P';
}

console.log(bytesToSize(234));
console.log(bytesToSize(2043));
console.log(bytesToSize(20433242));
console.log(bytesToSize(2043324243));
console.log(bytesToSize(2043324268233));
console.log(bytesToSize(2043324268233343));

Comments

3

This solution builds upon previous solutions, but takes into account both metric and binary units:

function formatBytes(bytes, decimals, binaryUnits) {
    if(bytes == 0) {
        return '0 Bytes';
    }
    var unitMultiple = (binaryUnits) ? 1024 : 1000; 
    var unitNames = (unitMultiple === 1024) ? // 1000 bytes in 1 Kilobyte (KB) or 1024 bytes for the binary version (KiB)
        ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']: 
        ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    var unitChanges = Math.floor(Math.log(bytes) / Math.log(unitMultiple));
    return parseFloat((bytes / Math.pow(unitMultiple, unitChanges)).toFixed(decimals || 0)) + ' ' + unitNames[unitChanges];
}

Examples:

formatBytes(293489203947847, 1);    // 293.5 TB
formatBytes(1234, 0);   // 1 KB
formatBytes(4534634523453678343456, 2); // 4.53 ZB
formatBytes(4534634523453678343456, 2, true));  // 3.84 ZiB
formatBytes(4566744, 1);    // 4.6 MB
formatBytes(534, 0);    // 534 Bytes
formatBytes(273403407, 0);  // 273 MB

1 Comment

It looks like the abbreviation for metric kilobytes should be kB. en.wikipedia.org/wiki/Kibibyte
2

I originally used @Aliceljm's answer for a file upload project I was working on, but recently ran into an issue where a file was 0.98kb but being read as 1.02mb. Here's the updated code I'm now using.

function formatBytes(bytes){
  var kb = 1024;
  var ndx = Math.floor( Math.log(bytes) / Math.log(kb) );
  var fileSizeTypes = ["bytes", "kb", "mb", "gb", "tb", "pb", "eb", "zb", "yb"];

  return {
    size: +(bytes / kb / kb).toFixed(2),
    type: fileSizeTypes[ndx]
  };
}

The above would then be called after a file was added like so

// In this case `file.size` equals `26060275` 
formatBytes(file.size);
// returns `{ size: 24.85, type: "mb" }`

Granted, Windows reads the file as being 24.8mb but I'm fine with the extra precision.

Comments

2

Here is a solid Effective way to convert bytes . Only thing you need is to install mathjs library for accurate calculation . Just copy paste .

import { multiply, divide, round } from "mathjs";

class Size {
  constructor(value, unit) {
    this.value = value;
    this.unit = unit.toUpperCase();
  }
}

async function byteToSize(bytes) {
  const B = 1;
  const KB = multiply(B, 1024);
  const MB = multiply(KB, 1024);
  const GB = multiply(MB, 1024);
  const TB = multiply(GB, 1024);
  const PB = multiply(TB, 1024);

  if (bytes <= KB) {
    // @returns BYTE

    const result = round(divide(bytes, B));
    const unit = `B`;

    return new Size(result, unit);
  }

  if (bytes <= MB) {
    // @returns KILOBYTE

    const result = round(divide(bytes, KB));
    const unit = `KB`;

    return new Size(result, unit);
  }

  if (bytes <= GB) {
    // @returns MEGABYTE

    const result = round(divide(bytes, MB));
    const unit = `MB`;

    return new Size(result, unit);
  }

  if (bytes <= TB) {
    // @returns GIGABYTE

    const result = round(divide(bytes, GB));
    const unit = `GB`;

    return new Size(result, unit);
  }

  if (bytes <= PB) {
    // @returns TERABYTE

    const result = divide(bytes, TB).toFixed(2);
    const unit = `TB`;

    return new Size(result, unit);
  }

  if (bytes >= PB) {
    // @returns PETABYTE

    const result = divide(bytes, PB).toFixed(2);
    const unit = `PB`;

    return new Size(result, unit);
  }
}

1 Comment

Upvoted because it's a good solution, but not applicable for those that cannot use await.
2
const byteConversion = (bytes: number, decimals = 2) => {
if (bytes === 0) return '0 B';

const kiloByte = 1000;
const decimal = decimals < 0 ? 0 : decimals;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

const i: number = Math.floor(Math.log(bytes) / Math.log(kiloByte));

return `${parseFloat((bytes / kiloByte ** i).toFixed(decimal))} ${sizes[i]}`;

};

Comments

2

You can use pretty-bytes library.

Install

npm install pretty-bytes

Usage

import prettyBytes from 'pretty-bytes';

prettyBytes(1337);
//=> '1.34 kB'

prettyBytes(100);
//=> '100 B'

// Display with units of bits
prettyBytes(1337, {bits: true});
//=> '1.34 kbit'

// Display file size differences
prettyBytes(42, {signed: true});
//=> '+42 B'

// Localized output using German locale
prettyBytes(1337, {locale: 'de'});
//=> '1,34 kB'

Comments

1

I am updating @Aliceljm answer here. Since the decimal place matters for 1,2 digit numbers, I am round off the first decimal place and keep the first decimal place. For 3 digit number, I am round off the units place and ignoring the all decimal places.

getMultiplers : function(bytes){
    var unit = 1000 ;
    if (bytes < unit) return bytes ;
    var exp = Math.floor(Math.log(bytes) / Math.log(unit));
    var pre = "kMGTPE".charAt(exp-1);
    var result = bytes / Math.pow(unit, exp);
    if(result/100 < 1)
        return (Math.round( result * 10 ) / 10) +pre;
    else
        return Math.round(result) + pre;
}

Comments

1

var SIZES = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

function formatBytes(bytes, decimals) {
  for(var i = 0, r = bytes, b = 1024; r > b; i++) r /= b;
  return `${parseFloat(r.toFixed(decimals))} ${SIZES[i]}`;
}

Comments

1

I just wanted to share my input. I had this problem so my solution is this. This will convert lower units to higher units and vice versa just supply the argument toUnit and fromUnit

export function fileSizeConverter(size: number, fromUnit: string, toUnit: string ): number | string {
  const units: string[] = ['B', 'KB', 'MB', 'GB', 'TB'];
  const from = units.indexOf(fromUnit.toUpperCase());
  const to = units.indexOf(toUnit.toUpperCase());
  const BASE_SIZE = 1024;
  let result: number | string = 0;

  if (from < 0 || to < 0 ) { return result = 'Error: Incorrect units'; }

  result = from < to ? size / (BASE_SIZE ** to) : size * (BASE_SIZE ** from);

  return result.toFixed(2);
}

I got the idea from here

Comments

1

I use Recursive and assign level variable for proper Unit.

function getReadableByte(count, decimal=0, level=0) {
    let unitList = ["Bytes", "KB", "MB", "GB", "TB", "PT"];

    if (count >= 1024.0 && (level+1 < unitList.length)) {
        return getReadableByte(count/1024, decimal, ++level)
    }
    return `${decimal ? (count).toFixed(decimal) : Math.round(count)}${unitList[level]}`
}

console.log(getReadableByte(120, 2))

1 Comment

Would help to explanain your solution (think of beginners reading it). Especially the more elegant but intermediate-level constructs like (a) unit-symbols as array, (b) recursion, (c) template-string.
1

I made a algorithm 7 times faster (works like a ninja):

function rafaelFormatBytes(number){
  if(number == null || number === undefined || number <= 0) {
    return '0 Bytes';
  }
  var scaleCounter = 0;
  var scaleInitials = [' Bytes',' KB',' MB',' GB',' TB',' PB',' EB',' ZB',' YB'];
  while (number >= 1024 && scaleCounter < scaleInitials.length - 1){
    number /= 1024;
    scaleCounter++;
  }
  if(scaleCounter >= scaleInitials.length) scaleCounter = scaleInitials.length - 1;
  var compactNumber = number.toFixed(2)
                              .replace(/\.?0+$/,'')
                              .replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  compactNumber += scaleInitials[scaleCounter];
  return compactNumber.trim();
}
var testNum = 0;

var startTime, endTime;

function start() {
  startTime = new Date();
};

function end() {
  endTime = new Date();
  var timeDiff = endTime - startTime; //in ms
  // strip the ms
  timeDiff /= 1000;

  // get seconds 
  var seconds = Math.round(timeDiff, 5);
  console.log(timeDiff + " seconds");
}

function formatBytes(a,b=2,k=1024){with(Math){let d=floor(log(a)/log(k));return 0==a?"0 Bytes":parseFloat((a/pow(k,d)).toFixed(max(0,b)))+" "+["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][d]}}

console.log(formatBytes(1000000000000000000000000000));
console.log(rafaelFormatBytes(1000000000000000000000000000));

start();
for(i=0; i<100000; i++){
    formatBytes(1000000000000000);
}
end();
start();
for(i=0; i<100000; i++){
    rafaelFormatBytes(1000000000000000);
}
end();

... and the output:

827.18 YB
827.18 YB
0.293 seconds
0.039 seconds

Jesus Christ!!!!

Comments

1

more flexible and considered max pow in sizes list (upgraded l2aelba answer)

function formatBytes(bytes, decimals = 2, isBinary = false) {
      const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; // or ['B', 'KB', 'MB', 'GB', 'TB']
    
      if (!+bytes) {
        return `0 ${sizes[0]}`;
      }
    
      const inByte = isBinary ? 1024 : 1000;
      const dm = decimals < 0 ? 0 : decimals;
    
      const pow = Math.floor(Math.log(bytes) / Math.log(inByte));
      const maxPow = Math.min(pow, sizes.length - 1);
    
      return `${parseFloat((bytes / Math.pow(inByte, maxPow)).toFixed(dm))} ${
        sizes[maxPow]
      }`;
    }

Comments

1

This worked for me with react, typescript.

export const FormatBytes = (bytes: number) => {
  const units = ['b', 'kb', 'mb', 'gb', 'tb'];

  let i = 0;

  for (i; bytes >= 1024 && i < 4; i++) {
    bytes /= 1024;
  }

  return `${bytes.toFixed(2)} ${units[i]}`;
};

Comments

0

This is how a byte should be shown to a human:

function bytesToHuman(bytes, decimals = 2) {
  // https://en.wikipedia.org/wiki/Orders_of_magnitude_(data)
  const units = ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"]; // etc

  let i = 0;
  let h = 0;

  let c = 1 / 1023; // change it to 1024 and see the diff

  for (; h < c && i < units.length; i++) {
    if ((h = Math.pow(1024, i) / bytes) >= c) {
      break;
    }
  }

  // remove toFixed and let `locale` controls formatting
  return (1 / h).toFixed(decimals).toLocaleString() + " " + units[i];
}

// test
for (let i = 0; i < 9; i++) {
  let val = i * Math.pow(10, i);
  console.log(val.toLocaleString() + " bytes is the same as " + bytesToHuman(val));

}

// let's fool around
console.log(bytesToHuman(1023));
console.log(bytesToHuman(1024));
console.log(bytesToHuman(1025));

Comments

0
function bytes2Size(byteVal){
    var units=["Bytes", "KB", "MB", "GB", "TB"];
    var kounter=0;
    var kb= 1024;
    var div=byteVal/1;
    while(div>=kb){
        kounter++;
        div= div/kb;
    }
    return div.toFixed(1) + " " + units[kounter];
}

3 Comments

This function is easy-to-understand and follow - you can implement it in any language. It's a repeated division of the byte value until you attain the byte level (unit) that is greater than 1kb
Just a quick note, There are differences between binary prefixes. Some follow SI base 10 rule and some follow base 2. You can read more here. However, if you consider k to be 1024, instead of dividsion, you can simply use shift operator like byteVal >> 10 . Also you would better use Math.trunc() to cast real numbers to integers instead ofdivision by 1.
Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually of higher quality, and are more likely to attract upvotes.
0

ONE-LINER

const b2s=t=>{let e=Math.log2(t)/10|0;return(t/1024**(e=e<=0?0:e)).toFixed(3)+"BKMGP"[e]};

console.log(b2s(0));
console.log(b2s(123));
console.log(b2s(123123));
console.log(b2s(123123123));
console.log(b2s(123123123123));
console.log(b2s(123123123123123));

Comments

0

Same answer from @Aliceljm , but in a "more didactic" way. Thanks! =D

function formatBytes(numBytes, decPlaces) {
    /* Adjust the number of bytes informed for the most appropriate metric according
    to its value.

    Args:
        numBytes (number): The number of bytes (integer);
        decPlaces (Optional[number])): The number of decimal places (integer). If
            it is "undefined" the value "2" will be adopted.

    Returns:
        string: The number adjusted together with the most appropriate metric. */

    if (numBytes === 0) {
        return "0 Bytes";
    }

    // NOTE: 1 KB is equal to 1024 Bytes. By Questor
    // [Ref(s).: https://en.wikipedia.org/wiki/Kilobyte ]
    var oneKByte = 1024;

    // NOTE: Treats if the "decPlaces" is "undefined". If it is "undefined" the value
    // "2" will be adopted. By Questor
    if (decPlaces === undefined || decPlaces === "") {
        decPlaces = 2;
    }

    var byteMtrcs = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
    // Byte Metrics

    // NOTE: Defines the factor for the number of bytes and the metric. By Questor
    var mtrcNumbFactor = Math.floor(Math.log(numBytes) / Math.log(oneKByte));
    // Metrics Number Factor

    return parseFloat((numBytes / Math.pow(oneKByte, mtrcNumbFactor)).
            toFixed(decPlaces)) + " " + byteMtrcs[mtrcNumbFactor];
}

Comments

0

I had a problem of meta data on files returning from the server with different size units. I used @Alicejim response and tried to do it more general. sharing the code here, maybe it will help someone.

enum SizeUnits {
   Bytes = 'Bytes',
   KB = 'KB',
   MB = 'MB',
   GB = 'GB',
   TB = 'TB',
   PB = 'PB',
   EB = 'EB',
   ZB = 'ZB',
   YB = 'YB'
}
function convertSizeUnites(size: number, sourceSizeUnits: SizeUnits, targetSizeUnits: SizeUnits) {
    const i = Object.keys(SizeUnits).indexOf(sourceSizeUnits);
    const sizeInBytes = size * Math.pow(1024, i);
    const j = Object.keys(SizeUnits).indexOf(targetSizeUnits);
    return sizeInBytes / Math.pow(1024, j);
}
function formatSize(size: number, measureUnit: SizeUnits, decimals = 2) {
    if (size === 0) return '0 Bytes';
    const sizeInBytes = convertSizeUnites(size, measureUnit, SizeUnits.Bytes);
    const dm = decimals < 0 ? 0 : decimals;
    const i = Math.floor(Math.log(sizeInBytes) / Math.log(1024));
    return parseFloat((sizeInBytes / Math.pow(1024, i)).toFixed(dm)) + ' ' + 
    Object.keys(SizeUnits)[i];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.