我得到这段代码通过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;
}

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


当前回答

根据al冰岛m的答案,我在小数点后去掉了0:

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

其他回答

这个解决方案建立在以前的解决方案的基础上,但同时考虑了公制和二进制单位:

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

例子:

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

根据al冰岛m的答案,我在小数点后去掉了0:

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

这是目前排名最高的答案的后续。

边界情况

我发现了一个边缘情况:非常少量的字节!具体来说,当字节数在-1和1之间(独占)时。

例如,考虑0.25字节。在这种情况下,Math.floor(Math.log(0.25) / Math.log(1024))将返回-1。由于-1不是一个有效的索引,formatBytes(0.25)将返回类似“0.25 undefined”的值。

下面是一个使用Wolfram Alpha的边缘情况的示例。

Fix

我通过添加Math来解决这个问题。马克斯(0,…):

数学。max(0, Math.floor(Math.log(bytes) / Math.log(1024))

数学。Max(0,…)确保索引值始终至少为0。

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

@ al冰岛jm也给出了同样的答案,但以一种“更说教”的方式。谢谢!= 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];
}