Maneira correta de converter o tamanho em bytes para KB, MB, GB em Javascript

Eu tenho esse código para converter o tamanho em bytes via PHP, PHP converter MB / KB conversão


Agora eu quero covert para humanos legível via JavaScript , tentei converter este código para JS para que fique assim ..

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

Esta é uma maneira correta de fazer? Ou outro melhor ou mais fácil ?

A partir disso: ( 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: Este é o código original, Por favor, use a versão corrigida abaixo. Aliceljm não ativa mais seu código copiado


Agora, versão corrigida: (pela comunidade do Stackoverflow, + Minificado pelo 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]); } 

Resultados:

 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 

Existem 2 maneiras reais de representar tamanhos quando relacionadas a bytes, elas são unidades SI (10 ^ 3) ou unidades IEC (2 ^ 10). Há também o JEDEC, mas seu método é ambíguo e confuso. Notei que os outros exemplos têm erros, como usar KB em vez de kB para representar um kilobyte, então decidi escrever uma function que resolverá cada um desses casos usando o intervalo de unidades de medida aceitas atualmente.

Há um bit de formatação no final que fará com que o número pareça um pouco melhor (pelo menos para os meus olhos) sinta-se à vontade para remover essa formatação se ela não atender ao seu propósito.

Apreciar.

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

Você pode usar a biblioteca filesizejs .

Aqui está um forro:

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

Ou até mesmo:

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

Usando a operação bit a bit seria uma solução melhor. Tente isso

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

De acordo com a resposta de Aliceljm , eu removi 0 após o decimal:

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

Eu originalmente usei a resposta de @Aliceljm para um projeto de upload de arquivos no qual eu estava trabalhando, mas recentemente encontrei um problema em que um arquivo tinha 0.98kb mas era lido como 1.02mb . Aqui está o código atualizado que estou usando agora.

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

O acima, em seguida, seria chamado depois que um arquivo foi adicionado como assim

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

Concedido, o Windows lê o arquivo como sendo 24.8mb mas estou bem com a precisão extra.

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

Estou atualizando a resposta do @Aliceljm aqui. Como a casa decimal é importante para números de 1,2 dígitos, eu arredondo a primeira casa decimal e mantenho a primeira casa decimal. Para o número de 3 dígitos, eu sou arredondar o lugar das unidades e ignorar todas as casas decimais.

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

Esta solução baseia-se em soluções anteriores, mas leva em consideração as unidades métricas e binárias:

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

Exemplos:

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

Tente esta solução simples.

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