Converting file size in bytes to human-readable string

后端 未结 19 1693
眼角桃花
眼角桃花 2020-11-28 17:58

I\'m using this function to convert a file size in bytes to a human-readable file size:

function getReadableFileSizeString(fileSizeInBytes) {
    var i = -1;         


        
相关标签:
19条回答
  • 2020-11-28 18:25

    For those who use Angular, there's a package called angular-pipes that has a pipe for this:

    File

    import { BytesPipe } from 'angular-pipes';
    

    Usage

    {{ 150 | bytes }} <!-- 150 B -->
    {{ 1024 | bytes }} <!-- 1 KB -->
    {{ 1048576 | bytes }} <!-- 1 MB -->
    {{ 1024 | bytes: 0 : 'KB' }} <!-- 1 MB -->
    {{ 1073741824 | bytes }} <!-- 1 GB -->
    {{ 1099511627776 | bytes }} <!-- 1 TB -->
    {{ 1073741824 | bytes : 0 : 'B' : 'MB' }} <!-- 1024 MB -->
    

    Link to the docs.

    0 讨论(0)
  • 2020-11-28 18:26

    Another example similar to those here

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

    It measures negligibly better performance than the others with similar features.

    0 讨论(0)
  • 2020-11-28 18:26
    1551859712 / 1024 = 1515488
    1515488 / 1024 = 1479.96875
    1479.96875 / 1024 = 1.44528198242188
    

    Your solution is correct. The important thing to realize is that in order to get from 1551859712 to 1.5, you have to do divisions by 1000, but bytes are counted in binary-to-decimal chunks of 1024, hence why the Gigabyte value is less.

    0 讨论(0)
  • 2020-11-28 18:27

    Here is a prototype to convert a number to a readable string respecting the new international standards.

    There are two ways to represent big numbers: You could either display them in multiples of 1000 = 10 3 (base 10) or 1024 = 2 10 (base 2). If you divide by 1000, you probably use the SI prefix names, if you divide by 1024, you probably use the IEC prefix names. The problem starts with dividing by 1024. Many applications use the SI prefix names for it and some use the IEC prefix names. The current situation is a mess. If you see SI prefix names you do not know whether the number is divided by 1000 or 1024

    https://wiki.ubuntu.com/UnitsPolicy

    http://en.wikipedia.org/wiki/Template:Quantities_of_bytes

    Object.defineProperty(Number.prototype,'fileSize',{value:function(a,b,c,d){
     return (a=a?[1e3,'k','B']:[1024,'K','iB'],b=Math,c=b.log,
     d=c(this)/c(a[0])|0,this/b.pow(a[0],d)).toFixed(2)
     +' '+(d?(a[1]+'MGTPEZY')[--d]+a[2]:'Bytes');
    },writable:false,enumerable:false});
    

    This function contains no loop, and so it's probably faster than some other functions.

    Usage:

    IEC prefix

    console.log((186457865).fileSize()); // default IEC (power 1024)
    //177.82 MiB
    //KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
    

    SI prefix

    console.log((186457865).fileSize(1)); //1,true for SI (power 1000)
    //186.46 MB 
    //kB,MB,GB,TB,PB,EB,ZB,YB
    

    i set the IEC as default because i always used binary mode to calculate the size of a file... using the power of 1024


    If you just want one of them in a short oneliner function:

    SI

    function fileSizeSI(a,b,c,d,e){
     return (b=Math,c=b.log,d=1e3,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
     +' '+(e?'kMGTPEZY'[--e]+'B':'Bytes')
    }
    //kB,MB,GB,TB,PB,EB,ZB,YB
    

    IEC

    function fileSizeIEC(a,b,c,d,e){
     return (b=Math,c=b.log,d=1024,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
     +' '+(e?'KMGTPEZY'[--e]+'iB':'Bytes')
    }
    //KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
    

    Usage:

    console.log(fileSizeIEC(7412834521));
    

    if you have some questions about the functions just ask

    0 讨论(0)
  • 2020-11-28 18:30

    Based on cocco's idea, here's a less compact -but hopefully more comprehensive- example.

    <!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> 
    
    0 讨论(0)
  • 2020-11-28 18:30

    Based on cocco's answer but slightly desugerified (honestly, ones I was comfortable with are remained/added) and doesn't show trailing zeros but still supports 0, hope to be useful for others:

    function fileSizeSI(size) {
        var e = (Math.log(size) / Math.log(1e3)) | 0;
        return +(size / Math.pow(1e3, e)).toFixed(2) + ' ' + ('kMGTPEZY'[e - 1] || '') + 'B';
    }
    
    
    // test:
    document.write([0, 23, 4322, 324232132, 22e9, 64.22e12, 76.22e15, 64.66e18, 77.11e21, 22e24].map(fileSizeSI).join('<br>'));

    0 讨论(0)
提交回复
热议问题