J'utilise cette fonction pour convertir une taille de fichier en octets en une taille de fichier lisible par l'homme:
function getReadableFileSizeString(fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};
Cependant, il semble que ce ne soit pas précis à 100%. Par exemple:
getReadableFileSizeString(1551859712); // output is "1.4 GB"
Cela ne devrait-il pas être "1.5 GB"
? Il semble que la division par 1024 perd de la précision. Est-ce que je me trompe totalement ou y a-t-il une meilleure façon de le faire?
Cela dépend si vous voulez utiliser la convention binaire ou décimale.
La RAM, par exemple, est toujours mesurée en binaire. Exprimer 1551859712 sous la forme ~ 1,4 Go est donc correct.
D'autre part, les fabricants de disques durs préfèrent utiliser le format décimal. Ils l'appelleraient donc ~ 1,6 Go.
Et pour ne pas déranger, les disquettes utilisent un mélange des deux systèmes: leur 1 Mo correspond en réalité à 1024 000 octets.
En voici un que j'ai écrit:
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if(Math.abs(bytes) < thresh) {
return bytes + ' B';
}
var units = si
? ['kB','MB','GB','TB','PB','EB','ZB','YB']
: ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
var u = -1;
do {
bytes /= thresh;
++u;
} while(Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1)+' '+units[u];
}
par exemple.
humanFileSize(5000,true)
> "5.0 kB"
humanFileSize(5000,false)
> "4.9 KiB"
humanFileSize(-10000000000000000000000000000)
> "-8271.8 YiB"
Un autre mode de réalisation du calcul
function humanFileSize(size) {
var i = Math.floor( Math.log(size) / Math.log(1024) );
return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
};
Voici un prototype permettant de convertir un nombre en une chaîne lisible respectant les nouvelles normes internationales.
Il y a deux façons de représenter de grands nombres: Vous pouvez soit afficher eux en multiples de 1000 = 10 3 (base 10) ou 1024 = 2 10 (base 2). Si si vous divisez par 1000, vous utilisez probablement les noms de préfixe SI, si vous Si vous divisez par 1024, vous utilisez probablement les noms de préfixe IEC. Le problème commence par diviser par 1024. De nombreuses applications utilisent le préfixe SI nom pour cela et certains utilisent les noms de préfixes IEC. La situation présente est un gâchis. Si vous voyez des noms de préfixe SI, vous ne savez pas si le nombre est divisé par 1000 ou 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});
Cette fonction ne contient pas loop
, elle est donc probablement plus rapide que d’autres fonctions.
Utilisation:
Préfixe IEC}
console.log((186457865).fileSize()); // default IEC (power 1024)
//177.82 MiB
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
Préfixe SI
console.log((186457865).fileSize(1)); //1,true for SI (power 1000)
//186.46 MB
//kB,MB,GB,TB,PB,EB,ZB,YB
j'ai défini le IEC par défaut car j'ai toujours utilisé le mode binaire pour calculer la taille d'un fichier ... en utilisant la puissance de 1024
Si vous voulez juste l’un d’eux dans une fonction oneliner courte:
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
Utilisation:
console.log(fileSizeIEC(7412834521));
si vous avez des questions sur les fonctions, il suffit de demander
sizeOf = function (bytes) {
if (bytes == 0) { return "0.00 B"; }
var e = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes/Math.pow(1024, e)).toFixed(2)+' '+' KMGTP'.charAt(e)+'B';
}
sizeOf (2054110009);
// => "1,91 Go"sizeOf (7054110);
// => "6.73 MB"sizeOf ((3 * 1024 * 1024));
// => "3.00 MB"
Solution en tant que composant ReactJS
Bytes = React.createClass({
formatBytes() {
var i = Math.floor(Math.log(this.props.bytes) / Math.log(1024));
return !this.props.bytes && '0 Bytes' || (this.props.bytes / Math.pow(1024, i)).toFixed(2) + " " + ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][i]
},
render () {
return (
<span>{ this.formatBytes() }</span>
);
}
});
UPDATE Pour ceux qui utilisent es6, voici une version sans état de ce même composant
const sufixes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const getBytes = (bytes) => {
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return !bytes && '0 Bytes' || (bytes / Math.pow(1024, i)).toFixed(2) + " " + sufixes[i];
};
const Bytes = ({ bytes }) => (<span>{ getBytes(bytes) }</span>);
Bytes.propTypes = {
bytes: React.PropTypes.number,
};
Sur la base de l’idée de cocco , voici un exemple moins compact mais, espérons-le, plus complet.
<!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>
Voici le mien - fonctionne aussi pour les très gros fichiers -_-
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;
}
Sur la base de la réponse de cocco mais légèrement désinsectisée (honnêtement, ceux avec lesquels je me sentais à l'aise sont restés/ajoutés) et ne montre pas les zéros à la fin, mais prend toujours en charge 0, espère être utile pour les autres:
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>'));
1551859712 / 1024 = 1515488
1515488 / 1024 = 1479.96875
1479.96875 / 1024 = 1.44528198242188
Votre solution est correcte. La chose importante à comprendre est que pour obtenir de 1551859712
à 1.5
, vous devez effectuer des divisions de 1 000, mais les octets sont comptés dans des fragments binaires à décimaux de 1024, d'où la valeur inférieure du gigaoctet.
Un autre exemple similaire à ceux ici
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';
}
Il mesure de manière négligeable une performance supérieure à celle des autres appareils dotés de fonctionnalités similaires.
Je voulais le comportement "gestionnaire de fichiers" (par exemple, l'Explorateur Windows) où le nombre de décimales est proportionnel à la taille du nombre. Apparemment, aucune des autres réponses ne le fait.
function humanFileSize(size) {
if (size < 1024) return size + ' B'
let i = Math.floor(Math.log(size) / Math.log(1024))
let num = (size / Math.pow(1024, i))
let round = Math.round(num)
num = round < 10 ? num.toFixed(2) : round < 100 ? num.toFixed(1) : round
return `${num} ${'KMGTPEZY'[i-1]}B`
}
Voici quelques exemples:
humanFileSize(0) // "0 B"
humanFileSize(1023) // "1023 B"
humanFileSize(1024) // "1.00 KB"
humanFileSize(10240) // "10.0 KB"
humanFileSize(102400) // "100 KB"
humanFileSize(1024000) // "1000 KB"
humanFileSize(12345678) // "11.8 MB"
humanFileSize(1234567890) // "1.15 GB"
Pour ceux qui utilisent Angular
, il existe un paquetage appelé angular-pipes
qui contient un tube pour cela:
Fichier
import { BytesPipe } from 'angular-pipes';
Utilisation
{{ 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 -->
laissez octets = 1024 * 10 * 10 * 10;
console.log (getReadableFileSizeString (octets))
retournera 1000.0Кб au lieu de 1MB