JavaScript에서 바이트 단위의 크기를 KB, MB, GB로 변환하는 올바른 방법


258

PHP를 통해이 코드 를 바이트 단위로 은밀하게 만들었습니다 .

이제 JavaScript를 사용하여 이러한 크기를 사람이 읽을 수있는 크기 로 변환하려고합니다 . 이 코드를 JavaScript로 변환하려고했는데 다음과 같습니다.

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

이것이 올바른 방법입니까? 더 쉬운 방법이 있습니까?


5
실제로 GiB, MiB 및 KiB로 변환됩니다. 이것은 파일 크기에 대한 표준이지만 항상 장치 크기에 대한 것은 아닙니다.
David Schwartz

답변:


761

이것으로부터 : ( source )

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

참고 : 이것은 원래 코드입니다. 아래 고정 버전을 사용하십시오. Aliceljm 은 더 이상 복사 한 코드를 활성화하지 않습니다.


이제 고정 버전이 축소되지 않고 ES6가 수정되었습니다. (커뮤니티 별)

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

이제 고정 버전 : (Stackoverflow의 커뮤니티에 의해 + 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]}

사용법 :

// formatBytes(bytes,decimals)

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

데모 / 소스 :

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>

추신 : 변경 k = 1000또는 sizes = ["..."]원하는대로 ( 비트 또는 바이트 )


8
(1) 왜 bytes = 0이 "n / a"입니까? "0 B"아닌가요? (2) Math.round에는 정밀도 매개 변수가 없습니다. 나는 더 잘 사용할 것이다(bytes / Math.pow(1024, i)).toPrecision(3)
15:50에

4
toFixed(n)아마도 toPrecision(n)모든 값에 대해 정확한 정밀도를 갖는 것보다 더 적합 할 것 입니다. 그리고 후행 0을 피하기 위해 (예 :) bytesToSize(1000) // return "1.00 KB"사용할 수 있습니다 parseFloat(x). 마지막 줄을 다음과 같이 바꾸는 것이 좋습니다 return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];. 이전 변경으로 결과는 다음과 같습니다. 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
나는 복수 형태가 0에 사용되는 생각 : '0 바이트'
니마

14
minify가 훌륭하다고 말하지만 stackexchange 답변에서 더 자세하고 읽기 쉬운 코드를 사용하는 것이 좋습니다.
donquixote

2
KB = SI 단위의 켈빈 바이트. 무의미한 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";
}

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

결과 :

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

15

filesizejs 라이브러리를 사용할 수 있습니다 .


1024 바이트는 1000 바이트가 아닌 1 KB이기 때문에이 라이브러리가 정확한 표현을 제공한다고 생각합니다 (여기 다른 솔루션에서 제공됨). 감사합니다 @maurocchi
WM

3
@WM 그 진술은 사실이 아닙니다. 1kB = 1000 바이트 Kibibyte에는 1024 바이트가 있습니다. 과거에는 혼동이 있었으므로이 두 용어는 크기의 차이를 정확하게 설명합니다.
Brennan T

2
@BrennanT 그것은 당신의 나이에 달려 있습니다. 1KB는 1024 바이트였으며 특정 연령대의 사람들은 여전히 ​​1024 바이트를 봅니다.
kojow7

14

바이트와 ​​관련하여 크기를 나타내는 두 가지 실제 방법이 있으며 SI 단위 (10 ^ 3) 또는 IEC 단위 (2 ^ 10)입니다. JEDEC도 있지만 그 방법은 모호하고 혼동됩니다. 다른 예제에는 킬로바이트를 나타내는 kB 대신 KB를 사용하는 것과 같은 오류가 있음을 알았으므로 현재 허용되는 측정 단위 범위를 사용하여 이러한 각 사례를 해결할 함수를 작성하기로 결정했습니다.

마지막에 숫자가 조금 나아 보이도록하는 형식화 비트가 있습니다 (적어도 내 눈에는) 그 목적에 맞지 않으면 해당 서식을 자유롭게 제거 할 수 있습니다.

즐겨.

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

13

하나의 라이너가 있습니다.

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

또는:

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


Nice !, 그러나 1k가 1024가 아닌 1000이라면?
l2aelba

2
이 계산 1k를 2 ^ 10으로, 1m를 2 ^ 20으로 처리합니다. 1k가 1000이 되길 원한다면 log10을 사용하도록 조금 변경할 수 있습니다.
iDaN5x 2019

1
다음은 1K를 1000으로 취급하는 버전입니다.val => 'BKMGT'[~~(Math.log10(val)/3)]
iDaN5x

1
이거 좋은데! 함수에서 원하는 전체 문자열을 반환하기 위해 이것을 확장했습니다.i = ~~(Math.log2(b)/10); return (b/Math.pow(1024,i)).toFixed(2) + ("KMGTPEZY"[i-1]||"") + "B"
v0rtex

4

비트 단위 연산을 사용하는 것이 더 나은 솔루션입니다. 이 시도

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

1
나머지 바이트를 얻습니다. 소수 부분을 제공합니다.
Buzz LIghtyear

1
100이 필요한 경우 그에 따라 비트를 이동하십시오.
Buzz LIghtyear


3
이해하거나 최소한 테스트하지 않고 인터넷에서 코드를 가져 가지 마십시오. 이것은 단순히 잘못된 코드의 좋은 예입니다. 3 ( "1Bytes"반환) 또는 400000을 전달하여 실행 해보십시오.
Amir Haghighat

10
Amir Haghighat님께, 이것은 제가 작성한 기본 코드입니다. javasript에서 32 비트의 정수 값을 게시하면 정수는 4 바이트이므로 코드가 작동하지 않습니다. 이것들은 당신이 알아야 할 기본 프로그래밍 정보입니다. Stackoverflow는 사람에게만 먹이를주고 숟가락으로 먹이는 것은 아닙니다.
Buzz LIghtyear

4

Aliceljm 의 답변 에 따르면 십진수 후 0을 제거했습니다.

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

2

필자는 원래 작업중인 파일 업로드 프로젝트에 @Aliceljm 의 답변을 사용 했지만 최근에 파일을 0.98kb읽을 수 있는 문제가 발생 했습니다 1.02mb. 지금 사용중인 업데이트 된 코드는 다음과 같습니다.

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

위와 같이 파일이 추가 된 후에 호출됩니다

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

물론 Windows는 파일을 그대로 읽지 24.8mb만 정밀도가 뛰어납니다.


2

이 솔루션은 이전 솔루션을 기반으로하지만 메트릭 및 이진 단위를 모두 고려합니다.

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

예 :

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

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


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


1

@Aliceljm 답변을 여기에서 업데이트하고 있습니다. 소수점 자리는 1,2 자리 숫자로 중요하므로 첫 번째 소수점 자리를 반올림하고 첫 번째 소수점 자리를 유지합니다. 3 자리 숫자의 경우 단위 자리를 반올림하고 소수점 이하 자릿수를 모두 무시합니다.

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

0

이것은 바이트가 사람에게 보여지는 방법입니다.

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

0

방금 입력 내용을 공유하고 싶었습니다. 이 문제가 있었으므로 내 해결책은 이것입니다. 이것은 더 높은 단위에 더 낮은 단위를 변환하고 그 반대는 반대 단지 인수를 제공 toUnit하고fromUnit

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

나는 여기 에서 아이디어를 얻었다


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

이 기능은 이해하기 쉽고 따르기 때문에 모든 언어로 구현할 수 있습니다. 1kb보다 큰 바이트 레벨 (단위)에 도달 할 때까지 반복적으로 바이트 값을 나눕니다
Kjut

이진 접두사에는 차이점이 있습니다. 일부는 SI 기본 10 규칙을 따르고 일부는 기본 2를 따릅니다 . 자세한 내용은 여기를 참조 하십시오 . 당신이 k는 대신 dividsion의 1024하다고 생각한다면, 당신은 간단하게 사용할 수있는 시프트 연산자를 같이 byteVal >> 10. 또한 실수 를 1로 나누지 않고 정수로 캐스트 하는 것이 더 좋습니다Math.trunc() .
Cunning

코드를 답변으로 게시하지 말고 코드의 기능과 질문의 문제를 해결하는 방법에 대한 설명도 제공하십시오. 설명이 포함 된 답변은 일반적으로 품질이 높으며 투표를 유도 할 가능성이 높습니다.
Mark Rotteveel

-7

이 간단한 해결 방법을 시도하십시오.

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");
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.