在 JavaScript 中将字节大小转换为 KB、MB、GB 的正确方法

IT技术 javascript byte converters
2021-02-04 15:29:05

我得到了这段代码,通过 PHP 以字节为单位隐藏大小。

现在我想使用 JavaScript将这些大小转换为人类可读的大小。我尝试将此代码转换为 JavaScript,如下所示:

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

这是这样做的正确方法吗?有没有更简单的方法?

6个回答

从这里:(来源

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

注意:这是原始代码,请使用下面的固定版本。


固定版本,未缩小和 ES6'ed:(由社区提供)

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

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

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

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

固定版本 (由 StackOverflow 社区提供,由JSCompress缩小

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

用法 :

// formatBytes(bytes,decimals)

formatBytes(1024);       // 1 KB
formatBytes('1024');     // 1 KB
formatBytes(1234);       // 1.21 KB
formatBytes(1234, 3);    // 1.205 KB

演示/源代码:

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

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

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

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

// ** Demo code **
var p = document.querySelector('p'),
    input = document.querySelector('input');
    
function setText(v){
    p.innerHTML = formatBytes(v);
}
// bind 'input' event
input.addEventListener('input', function(){ 
    setText( this.value )
})
// set initial text
setText(input.value);
<input type="text" value="1000">
<p></p>

PS:更改k = 1000sizes = ["..."]根据需要(字节

(1) 为什么 bytes = 0 是“n/a”?不就是“0B”吗?(2) Math.round 没有精度参数。我最好用(bytes / Math.pow(1024, i)).toPrecision(3)
2021-03-14 15:29:05
我相信复数形式用于 0: '0 Bytes'
2021-03-14 15:29:05
我会说 minify 很好,但在 stackexchange 答案中,最好有更详细和可读的代码。
2021-03-14 15:29:05
KB = SI 单位的开尔文字节。这是荒谬的。应该是kB。
2021-03-23 15:29:05
toFixed(n)可能比toPrecision(n)对所有值具有一致的精度更合适为了避免尾随零(例如:),bytesToSize(1000) // return "1.00 KB"我们可以使用parseFloat(x). 我建议将最后一行替换为:return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];与以往的变化的结果是: bytesToSize(1000) // return "1 KB"/ bytesToSize(1100) // return "1.1 KB"/ bytesToSize(1110) // return "1.11 KB/ bytesToSize(1111) // also return "1.11 KB"
2021-03-26 15:29:05
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
    var teraBytes = marker * marker * marker * marker; // One TB is 1024 GB

    // 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";
}
我根据你的代码做了一个小提琴基础:jsfiddle.net/darkkyoun/3g71k6ho/16 希望它能帮助别人
2021-03-25 15:29:05
不使用太字节?
2021-04-01 15:29:05

此解决方案包括一个小数点和一个十分位数字(如果提供的 KB 或更多单位少于 10 个)

const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
   
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]);
}

结果:

niceBytes(435)                 // 435 bytes
niceBytes(3398)                // 3.3 KB
niceBytes(490398)              // 479 KB
niceBytes(6544528)             // 6.2 MB
niceBytes(23483023)            // 22 MB
niceBytes(3984578493)          // 3.7 GB
niceBytes(30498505889)         // 28 GB
niceBytes(9485039485039445)    // 8.4 PB
谢谢! 压缩: 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]}
2021-04-05 15:29:05

这是一个单班轮:

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

甚至:

val => 'BKMGT'[~~(Math.log2(val)/10)]
很好!,但是如果 1k 是 1024 而不是 1000 ?
2021-03-16 15:29:05
这很好!我对此进行了扩展以从我的函数中返回我想要的完整字符串:i = ~~(Math.log2(b)/10); return (b/Math.pow(1024,i)).toFixed(2) + ("KMGTPEZY"[i-1]||"") + "B"
2021-03-19 15:29:05
该计算处理1K为2 ^ 10,1M 2 ^ 20等。如果您希望 1k 为 1000,您可以稍微更改一下以使用 log10。
2021-04-04 15:29:05
这是一个将 1K 视为 1000 的版本: val => 'BKMGT'[~~(Math.log10(val)/3)]
2021-04-06 15:29:05

您可以使用filesizejs库。

对于来这里找库的人来说,这里是更好的一个:npmjs.com/package/pretty-bytes
2021-03-13 15:29:05
我猜这个库给出了准确的表示,因为 1024 字节是 1 KB,而不是 1000 字节(由此处的其他一些解决方案提供)。谢谢@maurocchi
2021-03-15 15:29:05
@BrennanT 这取决于你的年龄。1KB 曾经是 1024 字节,大多数超过一定年龄的人仍然如此看待它。
2021-03-19 15:29:05
@WM 那句话是不正确的。1kB = 1000 字节。Kibibyte 中有 1024 个字节。过去一直存在混淆,因此这两个术语准确地解释了大小的差异。
2021-04-03 15:29:05