我使用这个函数将文件大小(以字节为单位)转换为人类可读的文件大小:

零二线函数 var i = -1; var byteUnits =[英国‘计划生育’‘兆’,‘和合’,‘PB’‘EB”、“ZB’,‘YB]; do { fileSizeInBytes /= 1024; 我+; while (fileSizeInBytes > 1024) 数学归来。max(fileSizeInBytes, 0.1)。toFixed(1) + byteUnits[i]; 的 控制台日志(getReadableFileSizeString (1551859712);//输出是“1.4 GB”

然而,这似乎不是百分之百准确的。例如:

getReadableFileSizeString(1551859712); // output is "1.4 GB"

不应该是“1.5 GB”吗?除以1024似乎失去了精度。是我完全误解了什么,还是有更好的办法?


当前回答

下面是另一个国际化的实现,用TypeScript编写:

const UNITS = ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte', 'petabyte']
const BYTES_PER_KB = 1000


/**
 * Format bytes as human-readable text.
 *
 * @param sizeBytes Number of bytes.
 *
 * @return Formatted string.
 */
export function humanFileSize(sizeBytes: number | bigint): string {
    let size = Math.abs(Number(sizeBytes))

    let u = 0
    while(size >= BYTES_PER_KB && u < UNITS.length-1) {
        size /= BYTES_PER_KB
        ++u
    }

    return new Intl.NumberFormat([], {
        style: 'unit',
        unit: UNITS[u],
        unitDisplay: 'short',
        maximumFractionDigits: 1,
    }).format(size)
}

将[]替换为像fr这样的语言代码,以强制进行默认以外的本地化。

console.log(humanFileSize(0))
console.log(humanFileSize(9))
console.log(humanFileSize(99))
console.log(humanFileSize(999))
console.log(humanFileSize(1000))
console.log(humanFileSize(1001))
console.log(humanFileSize(1023))
console.log(humanFileSize(1024))
console.log(humanFileSize(1025))
console.log(humanFileSize(100_000))
console.log(humanFileSize(1_000_000))
console.log(humanFileSize(1_000_000_000))
console.log(humanFileSize(1_000_000_000_000))
console.log(humanFileSize(1_000_000_000_000_000))
console.log(humanFileSize(1_000_000_000_000_000_000))
// fr
0 o
9 o
99 o
999 o
1 ko
1 ko
1 ko
1 ko
1 ko
100 ko
1 Mo
1 Go
1 To
1 Po
1 000 Po

// en-US
0 byte
9 byte
99 byte
999 byte
1 kB
1 kB
1 kB
1 kB
1 kB
100 kB
1 MB
1 GB
1 TB
1 PB
1,000 PB

你可以得到国际。NumberFormat为您自动进行单位转换。如。

const sizeFormatter = new Intl.NumberFormat([], { style: 'unit', unit: 'byte', notation: "compact", unitDisplay: "narrow", }) console.log(sizeFormatter.format(0)) console.log(sizeFormatter.format(1)) console.log(sizeFormatter.format(999)) console.log(sizeFormatter.format(1000)) console.log(sizeFormatter.format(1023)) console.log(sizeFormatter.format(1024)) console.log(sizeFormatter.format(1024**2)) console.log(sizeFormatter.format(1024**3)) console.log(sizeFormatter.format(1024**4)) console.log(sizeFormatter.format(1024**5)) console.log(sizeFormatter.format(1024**6))

...但是单位有点奇怪。例如1024**4是1.1BB,我猜是“十亿字节”;我不认为有人会用它,即使它在技术上是正确的。

其他回答

基于cocco的想法,这里有一个不太紧凑但希望更全面的示例。

<!DOCTYPE html>
<html>
<head>
<title>File info</title>

<script>
<!--
function fileSize(bytes) {
    var exp = Math.log(bytes) / Math.log(1024) | 0;
    var result = (bytes / Math.pow(1024, exp)).toFixed(2);

    return result + ' ' + (exp == 0 ? 'bytes': 'KMGTPEZY'[exp - 1] + 'B');
}

function info(input) {
    input.nextElementSibling.textContent = fileSize(input.files[0].size);
} 
-->
</script>
</head>

<body>
<label for="upload-file"> File: </label>
<input id="upload-file" type="file" onchange="info(this)">
<div></div>
</body>
</html> 

我发现@cocco的回答很有趣,但有以下问题:

不要修改原生类型或您不拥有的类型 为人类编写干净、可读的代码,让最小化器为机器优化代码 (对TypeScript用户的奖励)不能很好地使用TypeScript

打字稿:

 /**
 * Describes manner by which a quantity of bytes will be formatted.
 */
enum ByteFormat {
  /**
   * Use Base 10 (1 kB = 1000 bytes). Recommended for sizes of files on disk, disk sizes, bandwidth.
   */
  SI = 0,
  /**
   * Use Base 2 (1 KiB = 1024 bytes). Recommended for RAM size, size of files on disk.
   */
  IEC = 1
}

/**
 * Returns a human-readable representation of a quantity of bytes in the most reasonable unit of magnitude.
 * @example
 * formatBytes(0) // returns "0 bytes"
 * formatBytes(1) // returns "1 byte"
 * formatBytes(1024, ByteFormat.IEC) // returns "1 KiB"
 * formatBytes(1024, ByteFormat.SI) // returns "1.02 kB"
 * @param size The size in bytes.
 * @param format Format using SI (Base 10) or IEC (Base 2). Defaults to SI.
 * @returns A string describing the bytes in the most reasonable unit of magnitude.
 */
function formatBytes(
  value: number,
  format: ByteFormat = ByteFormat.SI
) {
  const [multiple, k, suffix] = (format === ByteFormat.SI
    ? [1000, 'k', 'B']
    : [1024, 'K', 'iB']) as [number, string, string]
  // tslint:disable-next-line: no-bitwise
  const exp = (Math.log(value) / Math.log(multiple)) | 0
  // or, if you'd prefer not to use bitwise expressions or disabling tslint rules, remove the line above and use the following:
  // const exp = value === 0 ? 0 : Math.floor(Math.log(value) / Math.log(multiple)) 
  const size = Number((value / Math.pow(multiple, exp)).toFixed(2))
  return (
    size +
    ' ' +
    (exp 
       ? (k + 'MGTPEZY')[exp - 1] + suffix 
       : 'byte' + (size !== 1 ? 's' : ''))
  )
}

// example
[0, 1, 1024, Math.pow(1024, 2), Math.floor(Math.pow(1024, 2) * 2.34), Math.pow(1024, 3), Math.floor(Math.pow(1024, 3) * 892.2)].forEach(size => {
  console.log('Bytes: ' + size)
  console.log('SI size: ' + formatBytes(size))
  console.log('IEC size: ' + formatBytes(size, 1) + '\n')
});

到2020年,你可以使用文件大小的npm包,它支持IEC(功率1024,默认),SI(功率1000)和JEDEC(替代SI单位符号)格式。

npm install file-size

import filesize from "filesize";

// outputs: 186.46 MB
filesize(186457865).human('si');

// outputs: 177.82 MiB
filesize(186457865).human();

https://www.npmjs.com/package/file-size

这是我的-也适用于真正大的文件-_-

function formatFileSize(size)
{
    var sizes = [' Bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB'];
    for (var i = 1; i < sizes.length; i++)
    {
        if (size < Math.pow(1024, i)) return (Math.round((size/Math.pow(1024, i-1))*100)/100) + sizes[i-1];
    }
    return size;
}

另一个类似的例子

function fileSize(b) {
    var u = 0, s=1024;
    while (b >= s || -b >= s) {
        b /= s;
        u++;
    }
    return (u ? b.toFixed(1) + ' ' : b) + ' KMGTPEZY'[u] + 'B';
}

它所衡量的性能比其他具有相似特性的算法好得可以忽略不计。