Cara yang benar untuk mengonversi ukuran dalam byte ke KB, MB, GB dalam JavaScript

258

Saya mendapatkan kode ini untuk ukuran terselubung dalam byte melalui PHP.

Sekarang saya ingin mengonversi ukuran tersebut ke ukuran yang dapat dibaca manusia menggunakan JavaScript. Saya mencoba mengonversi kode ini ke JavaScript, yang terlihat seperti ini:

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

Apakah ini cara yang benar untuk melakukan ini? Apakah ada cara yang lebih mudah?

l2aelba
sumber
5
Ini sebenarnya dikonversi ke GiB, MiB, dan KiB. Ini standar untuk ukuran file, tetapi tidak selalu untuk ukuran perangkat.
David Schwartz

Jawaban:

761

Dari ini: ( sumber )

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

Catatan: Ini adalah kode asli, Silakan gunakan versi tetap di bawah ini. Aliceljm tidak lagi mengaktifkan kode yang disalinnya


Sekarang, Fixed versi tidak ditambang, dan ES6'ed: (oleh komunitas)

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

Sekarang, versi Tetap: (oleh komunitas Stackoverflow, + Diminimalkan oleh JSCompress )

function formatBytes(a,b=2){if(0===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","KB","MB","GB","TB","PB","EB","ZB","YB"][d]}

Penggunaan:

// formatBytes(bytes,decimals)

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

Demo / sumber:

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: Ubah k = 1000atau sizes = ["..."]seperti yang Anda inginkan ( bit atau byte )

Aliceljm
sumber
8
(1) mengapa byte = 0 adalah "n / a"? Bukankah itu hanya "0 B"? (2) Math.round tidak memiliki parameter presisi. Saya sebaiknya menggunakan(bytes / Math.pow(1024, i)).toPrecision(3)
disfated
4
toFixed(n)mungkin lebih tepat daripada toPrecision(n)memiliki presisi yang konsisten untuk semua nilai. Dan untuk menghindari trailing zero (ex:) bytesToSize(1000) // return "1.00 KB"kita bisa menggunakan parseFloat(x). Saya sarankan untuk mengganti baris terakhir oleh: return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];. Dengan perubahan sebelumnya, hasilnya adalah: bytesToSize(1000) // return "1 KB"/ bytesToSize(1100) // return "1.1 KB"/ bytesToSize(1110) // return "1.11 KB/ bytesToSize(1111) // also return "1.11 KB"
MathieuLescure
3
Saya percaya bentuk jamak digunakan untuk 0: '0 Bytes'
nima
14
Saya akan mengatakan minify itu bagus, tetapi dalam jawaban stackexchange lebih baik memiliki kode yang lebih verbose dan mudah dibaca.
donquixote
2
KB = Kelvin byte dalam satuan SI. yang tidak masuk akal. Itu harus kB.
Brennan T
47
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";
}
Jayram
sumber
34
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;
  }
  //include a decimal point and a tenths-place digit if presenting 
  //less than ten of KB or greater units
  return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]);
}

Hasil:

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
Faust
sumber
15

Anda dapat menggunakan perpustakaan filesizejs .

maurocchi
sumber
Saya kira perpustakaan ini memberikan representasi yang akurat, karena 1024 byte adalah 1 KB, bukan 1000 byte (seperti yang disediakan oleh beberapa solusi lain di sini). Terima kasih @maurocchi
WM
3
@ WM pernyataan itu tidak benar. 1kB = 1000 byte. Ada 1024 byte dalam Kibibyte. Ada kebingungan di masa lalu sehingga dua istilah ini justru menjelaskan perbedaan ukuran.
Brennan T
2
@ BriannanT Tergantung usia Anda. 1KB dulu 1024 byte dan kebanyakan orang di atas usia tertentu masih melihatnya seperti itu.
kojow7
14

Ada 2 cara nyata untuk merepresentasikan ukuran ketika dihubungkan dengan byte, yaitu satuan SI (10 ^ 3) atau satuan IEC (2 ^ 10). Ada juga JEDEC tetapi metode mereka ambigu dan membingungkan. Saya perhatikan contoh-contoh lain memiliki kesalahan seperti menggunakan KB dan bukan kB untuk mewakili satu kilobyte jadi saya memutuskan untuk menulis fungsi yang akan menyelesaikan masing-masing kasus menggunakan kisaran satuan ukuran yang saat ini diterima.

Ada sedikit format di akhir yang akan membuat angka terlihat sedikit lebih baik (setidaknya bagi saya) merasa bebas untuk menghapus format itu jika tidak sesuai dengan tujuan Anda.

Nikmati.

// 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];
    }
}
Brennan T
sumber
13

Inilah satu kalimat:

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

Atau bahkan:

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

iDaN5x
sumber
Bagus !, Tetapi jika 1k adalah 1024 bukan 1000?
l2aelba
2
Perhitungan ini memperlakukan 1k sebagai 2 ^ 10, 1m sebagai 2 ^ 20 dan seterusnya. jika Anda ingin 1k menjadi 1000, Anda dapat mengubahnya sedikit untuk menggunakan log10.
iDaN5x
1
Berikut adalah versi yang memperlakukan 1K sebagai 1000:val => 'BKMGT'[~~(Math.log10(val)/3)]
iDaN5x
1
Ini bagus! Saya memperluas ini untuk mengembalikan string penuh yang saya inginkan dari fungsi saya:i = ~~(Math.log2(b)/10); return (b/Math.pow(1024,i)).toFixed(2) + ("KMGTPEZY"[i-1]||"") + "B"
v0rtex
4

Menggunakan operasi bitwise akan menjadi solusi yang lebih baik. Coba ini

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 ;
}
Buzz lightyear
sumber
1
Dapatkan byte yang tersisa. Itu akan memberikan bagian desimal.
Buzz LIghtyear
1
Ini 1024. Jika Anda memerlukan 100 shift bit sesuai.
Buzz LIghtyear
2
tautan
Buzz LIghtyear
3
Tolong jangan ambil kode dari internet tanpa memahaminya atau setidaknya mengujinya. Ini adalah contoh kode yang baik yang benar-benar salah. Coba jalankan dengan melewatkannya 3 (mengembalikan "1Bytes") atau 400000.
Amir Haghighat
10
Dear Amir Haghighat, ini adalah kode dasar yang hanya ditulis oleh saya. Dalam posting javasript 32 bit nilai integer kode tidak akan berfungsi karena integer hanya empat byte. Ini adalah info pemrograman dasar yang harus Anda ketahui. Stackoverflow dimaksudkan hanya untuk membimbing orang dan tidak memberi makan sendok.
Buzz LIghtyear
4

Menurut jawaban Aliceljm , saya menghapus 0 setelah desimal:

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];
}
abla
sumber
2

Saya awalnya menggunakan jawaban @Aliceljm untuk proyek upload file yang sedang saya kerjakan, tetapi baru-baru ini mengalami masalah di mana file itu 0.98kbtetapi sedang dibaca sebagai 1.02mb. Inilah kode yang diperbarui yang sekarang saya gunakan.

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

Di atas kemudian akan dipanggil setelah file ditambahkan seperti itu

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

Memang, Windows membaca file sebagai 24.8mbtetapi saya baik-baik saja dengan ketepatan ekstra.

theOneWhoKnocks
sumber
2

Solusi ini dibangun berdasarkan solusi sebelumnya, tetapi memperhitungkan satuan metrik dan biner:

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

Contoh:

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
TxRegex
sumber
2

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

jasee
sumber
2

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

Priladnykh Ivan
sumber
1

Saya memperbarui jawaban @Aliceljm di sini. Karena tempat desimal penting untuk angka 1,2 digit, saya melengkapi tempat desimal pertama dan mempertahankan tempat desimal pertama. Untuk 3 digit angka, saya melengkapi tempat unit dan mengabaikan semua tempat desimal.

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;
}
omkar
sumber
0

Beginilah seharusnya byte ditampilkan ke manusia:

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));
Eugen Mihailescu
sumber
0

Saya hanya ingin membagikan masukan saya. Saya punya masalah ini jadi solusi saya adalah ini. Ini akan mengkonversi unit yang lebih rendah ke unit yang lebih tinggi dan sebaliknya hanya memberikan argumen toUnitdanfromUnit

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

Saya mendapat ide dari sini

aRtoo
sumber
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];
}
Kjut
sumber
Fungsi ini mudah dipahami dan diikuti - Anda dapat mengimplementasikannya dalam bahasa apa pun. Ini adalah pembagian berulang dari nilai byte hingga Anda mencapai level byte (unit) yang lebih besar dari 1kb
Kjut
Hanya catatan singkat, Ada perbedaan antara awalan biner. Beberapa mengikuti aturan SI base 10 dan beberapa mengikuti base 2. Anda dapat membaca lebih lanjut di sini . Namun, jika Anda menganggap k sebagai 1024, alih-alih pembagian, Anda cukup menggunakan shift operator seperti byteVal >> 10. Juga Anda akan lebih baik menggunakan Math.trunc()untuk melemparkan bilangan real ke bilangan bulat daripada pembagian dengan 1.
Licik
Tolong jangan posting kode hanya sebagai jawaban, tetapi juga berikan penjelasan apa yang kode Anda lakukan dan bagaimana memecahkan masalah pertanyaan. Jawaban dengan penjelasan biasanya berkualitas lebih tinggi, dan lebih cenderung menarik upvotes.
Mark Rotteveel
-7

Coba solusi sederhana ini.

var files = $("#file").get(0).files;               
                var size = files[0].size;
                if (size >= 5000000) {
alert("File size is greater than or equal to 5 MB");
}
Liladhar
sumber