Modo corretto per convertire le dimensioni in byte in KB, MB, GB in Javascript

Ho ottenuto questo codice in dimensioni segrete in byte tramite PHP, conversione di file MB in KB e KB


Ora non voglio essere leggibile tramite l’uso di Javascript , ho provato a convertire questo codice in JS quindi assomiglia a questo ..

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 byte';} return bytes; } 

Questo è un modo corretto di fare? O un altro migliore o più facile ?

Da questo: ( fonte )

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

Nota: questo è il codice originale, si prega di utilizzare la versione fissa di seguito. Aliceljm non triggers più il suo codice copiato


Ora, versione fissa: (dalla comunità di Stackoverflow, + Minified by JSCompress )

 function formatBytes(a,b){if(0==a)return"0 Bytes";var c=1024,d=b||2,e=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],f=Math.floor(Math.log(a)/Math.log(c));return parseFloat((a/Math.pow(c,f)).toFixed(d))+" "+e[f]} 

Uso:

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

Demo / fonte:

 function formatBytes(bytes,decimals) { if(bytes == 0) return '0 Bytes'; var k = 1024, dm = decimals || 2, sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], 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); 
  

 function formatBytes(bytes) { if(bytes < 1024) return bytes + " Bytes"; else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KB"; else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MB"; else return(bytes / 1073741824).toFixed(3) + " GB"; }; 
 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 < 1 ? 0 : 1) + ' ' + units[l]); } 

risultati:

 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 

Esistono 2 modi reali per rappresentare le dimensioni quando sono correlate ai byte, sono unità SI (10 ^ 3) o unità IEC (2 ^ 10). C’è anche JEDEC ma il loro metodo è ambiguo e confuso. Ho notato che gli altri esempi hanno errori come usare KB invece di kB per rappresentare un kilobyte, così ho deciso di scrivere una funzione che risolverà ognuno di questi casi usando l’intervallo di unità di misura attualmente accettate.

C’è un bit di formattazione alla fine che renderà il numero un po ‘migliore (almeno ai miei occhi), sentitevi liberi di rimuovere quella formattazione se non si adatta al vostro scopo.

Godere.

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

Puoi usare la libreria filesizejs .

Ecco una fodera:

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

O anche:

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

Utilizzare l’operazione bit a bit sarebbe una soluzione migliore. Prova questo

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

Secondo la risposta di Aliceljm , ho rimosso 0 dopo il decimale:

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

Inizialmente ho utilizzato la risposta di @Aliceljm per un progetto di caricamento file su cui stavo lavorando, ma di recente ho riscontrato un problema in cui un file era 0.98kb ma veniva letto come 1.02mb . Ecco il codice aggiornato che sto usando ora.

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

Il precedente sarebbe quindi chiamato dopo che un file è stato aggiunto in questo modo

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

Certo, Windows legge il file come 24.8mb ma sto bene con la precisione in più.

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

Sto aggiornando la risposta @Aliceljm qui. Dato che la cifra decimale è importante per numeri a 1,2 cifre, arrotondare la prima cifra decimale e mantenere la prima cifra decimale. Per il numero a 3 cifre, torno dal posto delle unità e ignorando tutte le posizioni decimali.

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

Questa soluzione si basa su soluzioni precedenti, ma tiene conto sia delle unità metriche che binari:

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

Esempi:

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

Prova questa soluzione semplice.

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