การแปลงขนาดไฟล์เป็นไบต์เป็นสตริงที่มนุษย์สามารถอ่านได้


239

ฉันใช้ฟังก์ชันนี้เพื่อแปลงขนาดไฟล์เป็นไบต์เป็นขนาดไฟล์ที่มนุษย์สามารถอ่านได้:

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

อย่างไรก็ตามดูเหมือนว่านี่จะไม่ถูกต้อง 100% ตัวอย่างเช่น:

getReadableFileSizeString(1551859712); // output is "1.4 GB"

สิ่งนี้ไม่ควรเป็น"1.5 GB"หรือ ดูเหมือนว่าการหารด้วย 1024 จะสูญเสียความแม่นยำ ฉันเข้าใจผิดบางอย่างหรือมีวิธีที่ดีกว่าในการทำสิ่งนี้หรือไม่?


3
getReadableFileSizeString (0); ส่งคืน 0.1kb; p
Daniel Magnusson

2
ทำไมมันควรเป็น 1.5 มัน1.445281982421875ถูกต้องที่ปัดเศษลงเป็น 1.4
mpen

1
1551859712 / (1024 ^ 3) = 1.445281982421875 ที่ถูกต้อง!
HM

2
YBฉันรักที่คุณเพิ่มเข้าไป ใครก็ตามที่สงสัยจะได้รับ 1 YB สำหรับฐานข้อมูลของเขา มันจะมีราคา100 ล้านล้านดอลลาร์ !
guyarad

4
@guyarad - มีรูปภาพที่มีชื่อเสียงของฮาร์ดไดรฟ์ 5MB จาก 50 ปีที่ผ่านมา (มีขนาดเท่าห้องและหนักประมาณตัน) ฉันแน่ใจแล้วว่าพวกเขาไม่ได้ฝันถึง GB และ TB และดูว่าเราอยู่ที่ไหนวันนี้ ... อย่าพูดว่าไม่ ;-)
TheCuBeMan

คำตอบ:


45

ขึ้นอยู่กับว่าคุณต้องการใช้การประชุมแบบไบนารีหรือทศนิยม

ตัวอย่างเช่น RAM จะวัดเสมอในไบนารีดังนั้นการแสดง 1551859712 เพราะ ~ 1.4GiB จะถูกต้อง

ในทางกลับกันผู้ผลิตฮาร์ดดิสก์ต้องการใช้ทศนิยมดังนั้นพวกเขาจึงเรียกมันว่า ~ 1.6GB

และเพื่อให้เกิดความสับสนฟลอปปี้ดิสก์ใช้ส่วนผสมของทั้งสองระบบ - 1MB ของพวกเขาคือจริง ๆ แล้ว 1024,000 ไบต์


3
อาหารมื้อเย็นที่ตลก ;-) "เพื่อให้เกิดความสับสนฟลอปปี้ดิสก์ใช้ส่วนผสมของทั้งสองระบบ - 1MB ของพวกเขาจริง ๆ แล้วคือ 1024,000 ไบต์"
FranXho

จริงขนาด RAM จะวัดโดยใช้หน่วย IEC ขนาดของดิสก์โดยใช้เมตริก .. มีโมดูล isomorphic npm ที่จะแปลงทั้งสองคือขนาดไบต์
Lloyd

351

นี่คือสิ่งที่ฉันเขียน:

function humanFileSize(bytes, si=false, dp=1) {
  const thresh = si ? 1000 : 1024;

  if (Math.abs(bytes) < thresh) {
    return bytes + ' B';
  }

  const units = si 
    ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] 
    : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
  let u = -1;
  const r = 10**dp;

  do {
    bytes /= thresh;
    ++u;
  } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);


  return bytes.toFixed(dp) + ' ' + units[u];
}


console.log(humanFileSize(5000, true))  // 5.0 kB
console.log(humanFileSize(5000, false))  // 4.9 KiB
console.log(humanFileSize(-10000000000000000000000000000))  // -8271.8 YiB
console.log(humanFileSize(999949, true))  // 999.9 kB
console.log(humanFileSize(999950, true))  // 1.0 MB
console.log(humanFileSize(999950, true, 2))  // 999.95 kB
console.log(humanFileSize(999500, true, 0))  // 1 MB


1
ฉันทำการปรับหนึ่งครั้ง: เมื่อประเมินเกณฑ์ให้ใช้ค่าสัมบูรณ์ วิธีนี้ฟังก์ชันจะรองรับค่าลบ ฟังก์ชั่นที่ดี! ขอบคุณที่ไม่ได้ใช้ข้อความสั่ง switch !!
Aaron Blenkush

20
@AaronBlenkush: คุณจะมีขนาดไฟล์เชิงลบเมื่อใด
mpen

14
ฉันเพิ่งคัดลอกฟังก์ชันของคุณไปยัง Google ชีตที่ฉันใช้เพื่อแสดงขนาดเดลต้าหลังจากการดำเนินการ "ล้างข้อมูล" ก่อนหลังและแตกต่าง การดำเนินการล้างข้อมูลทำให้การเติบโตของตารางฐานข้อมูลบางส่วนและการลดลงของตารางอื่น ๆ ตัวอย่างเช่นตาราง A มีความแตกต่างของ -1.95 MB ในขณะที่ตาราง B มีความแตกต่างของ 500 kB ดังนั้น: บวกและลบ :-)
Aaron Blenkush

นี่คือเวอร์ชันที่บีบอัดของสคริปต์:function humanFileSize(B,i){var e=i?1e3:1024;if(Math.abs(B)<e)return B+" B";var a=i?["kB","MB","GB","TB","PB","EB","ZB","YB"]:["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],t=-1;do B/=e,++t;while(Math.abs(B)>=e&&t<a.length-1);return B.toFixed(1)+" "+a[t]}
RAnders00

1
@ RAnders00: ขอบคุณสำหรับเวอร์ชั่นย่อ คุณบอกฉันได้ไหมว่าทำไมคุณถึงใส่อักขระ Unicode สองตัวที่มองไม่เห็น U + 200C (ZERO WIDTH NON-JOINER) และ U + 200B (ZERO WIDTH SPACE) หลังจากE oft EiB ? นี่เป็นจุดประสงค์เพื่อเป็นลายน้ำเพื่อให้คุณสามารถติดตามผู้ที่ใช้รหัสนี้ได้หรือไม่ ถ้าเป็นเช่นนั้นฉันคิดว่าคุณควรทำให้โพสต์ของคุณโปร่งใส
เลวีอาธาน

81

ศูนย์รวมของการคำนวณอีก

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

8
ดูเหมือนจะไม่จัดการ 0
Offirmo

4
มันทำหรือไม่จัดการ 0? ท้ายที่สุดนี่คือถ้า (ขนาด == 0) {} else {} ยังคงสง่างามกว่าที่ฉันเคยเห็น
Rodrigo

13
การเปลี่ยนบรรทัดแรกvar i = size == 0 ? 0 : Math.floor( Math.log(size) / Math.log(1024) );ดูเหมือนจะทำเคล็ดลับถ้าเป็น 0 มันจะส่งกลับ "0 B"
กาวิน

เพียงแค่ FYI; ฉันรู้ว่าคำตอบคือ JavaScript ธรรมดา แต่ถ้ามีคนไม่ต้องการใช้ใน TypeScript มันไม่ทำงาน (พิมพ์ไม่ถูกต้องในขณะที่คุณทำtoFixedแล้วทำคณิตศาสตร์กับสตริง* 1ทำอะไรได้บ้าง
Frexuz

1
*1เปลี่ยนแปลงชนิดข้อมูลจากสตริงไปยังหมายเลขดังนั้นสำหรับค่าที่1024คุณจะได้รับแทน1 kB 1.00 kBคุณสามารถทำให้ TypeScript มีความสุขได้ด้วยการทำNumber((size / Math.pow(1024, i)).toFixed(2))สิ่งเดียวกันให้สำเร็จ
Adrian T

38

นี่คือต้นแบบในการแปลงตัวเลขเป็นสตริงที่อ่านได้ซึ่งเป็นไปตามมาตรฐานสากลใหม่

มีสองวิธีในการแสดงตัวเลขขนาดใหญ่: คุณสามารถแสดงเป็นทวีคูณของ 1000 = 10 3 (ฐาน 10) หรือ 1024 = 2 10 (ฐาน 2) หากคุณหารด้วย 1,000 คุณอาจใช้ชื่อคำนำหน้า SI หากคุณหารด้วย 1024 คุณอาจใช้ชื่อคำนำหน้า IEC ปัญหาเริ่มต้นด้วยการหารด้วย 1024 แอปพลิเคชันจำนวนมากใช้ชื่อคำนำหน้า SI สำหรับมันและบางโปรแกรมใช้ชื่อคำนำหน้า IEC สถานการณ์ปัจจุบันไม่เป็นระเบียบ หากคุณเห็นชื่อคำนำหน้า SI คุณไม่ทราบว่าหมายเลขนั้นหารด้วย 1,000 หรือ 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});

ฟังก์ชั่นนี้ไม่มีloopและอาจเร็วกว่าฟังก์ชั่นอื่น ๆ

การใช้งาน:

คำนำหน้า IEC

console.log((186457865).fileSize()); // default IEC (power 1024)
//177.82 MiB
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB

คำนำหน้า SI

console.log((186457865).fileSize(1)); //1,true for SI (power 1000)
//186.46 MB 
//kB,MB,GB,TB,PB,EB,ZB,YB

ฉันตั้งค่า IEC เป็นค่าเริ่มต้นเพราะฉันใช้โหมดเลขฐานสองเสมอในการคำนวณขนาดของไฟล์ ... โดยใช้กำลัง 1024


หากคุณต้องการเพียงหนึ่งในฟังก์ชั่น oneliner สั้น ๆ :

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

การใช้งาน:

console.log(fileSizeIEC(7412834521));

หากคุณมีคำถามเกี่ยวกับฟังก์ชั่นก็ถาม


รหัสกะทัดรัดดีมากฉันเองจะเพิ่มอักขระพิเศษสองสามตัวเพื่อควบคุมตำแหน่งทศนิยม
Orwellophile

Hi! จริงๆแล้วรหัสคือวิธีที่ฉันเขียนมันเป็นครั้งแรกใน jsfiddle ในปีที่ผ่านมาฉันเรียนรู้ที่จะใช้ชวเลขและค่าบิต อุปกรณ์มือถือช้าอินเทอร์เน็ตช้าพื้นที่ไม่มาก ... ทำอย่างนั้นฉันจึงประหยัดเวลาได้มาก แต่นั่นไม่ใช่ทั้งหมดความสมบูรณ์แบบโดยรวมเพิ่มขึ้นในทุกเบราว์เซอร์และโค้ดทั้งหมดโหลดเร็วกว่ามาก ... ฉันไม่ได้ใช้ jQuery ดังนั้นฉันจึงไม่ต้องโหลด 100kb ทุกครั้ง ฉันต้องบอกว่าฉันเขียนจาวาสคริปต์ในไมโครคอนโทรลเลอร์, สมาร์ททีวี, เกมคอนโซล ที่มีพื้นที่ จำกัด (MCU), ประสิทธิภาพ (SmartTV's) และบางครั้งการเชื่อมต่อช้า (มือถือ)
cocco

กล่าวว่าฉันหวังว่าคุณจะเข้าใจตัวเลือกของฉัน ทั้งหมดที่ฉันทำได้คืออธิบายสิ่งที่คุณไม่เข้าใจหรือในอีกด้านหนึ่งฉันมีความสุขเสมอที่ได้เรียนรู้สิ่งใหม่ หากมีบางอย่างในรหัสของฉันที่สามารถเพิ่มประสิทธิภาพหรือประหยัดพื้นที่ฉันยินดีที่จะได้ยิน
cocco

18
การลดขนาดควรเป็นส่วนหนึ่งของกระบวนการสร้างไม่ใช่รูปแบบการเข้ารหัสของคุณ ไม่มีนักพัฒนาที่จริงจังจะใช้รหัสนี้เพราะมันใช้เวลานานเกินไปในการอ่านและตรวจสอบความถูกต้อง
huysentruitw

1
สำหรับผู้ที่เกลียดที่จะเห็น "15.00 Bytes" คุณสามารถแก้ไขส่วนนี้ได้เล็กน้อย:.toFixed(e ? 2 : 0)
Lukman

20
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 GB"

sizeof (7054110);
// => "6.73 MB"

sizeOf ((3 * 1024 * 1024));
// => "3.00 MB"


2
หากคุณต้องการที่จะกำจัดของพื้นที่พิเศษสำหรับไบต์คุณสามารถใช้พื้นที่กว้างเป็นศูนย์:\u200b '\u200bKMGTP'
cdmckay

15

โซลูชันเป็นส่วนประกอบ 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>
        );
    }
});

อัพเดท สำหรับผู้ใช้ es6 ที่นี่เป็นรุ่นไร้สัญชาติขององค์ประกอบเดียวกันนี้

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

1
เยี่ยมมากขอบคุณ คุณลืม "bytes" ใน Math.log () ในบรรทัดแรกของฟังก์ชัน
getBytes

ดีมาก. สำหรับการแก้ความกำกวมและด้วยสัญกรณ์ ES6 คุณอาจใช้สิ่งนี้: return (! bytes && '0 Bytes') || ${(bytes / (1024 ** i)).toFixed(2)} ${suffixes[i]};
สมองน้อย

12

จากความคิดของcoccoนี่คือตัวอย่างที่มีขนาดกะทัดรัดน้อยลง แต่หวังว่าจะครอบคลุมมากขึ้น

<!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> 

8

ฉันต้องการพฤติกรรม "ตัวจัดการไฟล์" (เช่น Windows Explorer) ซึ่งจำนวนตำแหน่งทศนิยมเป็นสัดส่วนกับขนาดของตัวเลข ดูเหมือนว่าไม่มีคำตอบอื่นใดที่จะทำเช่นนี้

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

นี่คือตัวอย่างบางส่วน:

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"

ใช้ toFixed แปลงเป็นสตริงดังนั้นรอบของคุณเป็นสตริงหรือตัวเลข นี่เป็นการฝึกฝนที่ไม่ดีคุณสามารถแปลงกลับเป็นตัวเลขได้อย่างง่ายดาย:+num.tofixed(2)
Vincent Duprez

ไม่.toPrecision(3)ครอบคลุมกรณีเหล่านี้ทั้งหมดหรือไม่ โอ้ .. ฉันเดาว่ามันไม่ครอบคลุมระหว่าง 1,000 และ 1,023 Bummer
mpen

7

อีกตัวอย่างที่คล้ายกับที่นี่

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

มันวัดประสิทธิภาพการทำงานที่ดีกว่าคนอื่นที่มีคุณสมบัติคล้ายกันโดยประมาท


สิ่งนี้ให้ประสิทธิภาพที่ดีกว่าคำตอบอื่น ๆ ฉันใช้สิ่งนี้ บางคนทำให้แท็บ Chrome ของฉันค้างและใช้ CPU 99.9% เมื่อฉันทำการคำนวณเป็นระยะ
Nir Lanka

5

นี่คือของฉัน - ใช้งานได้กับไฟล์ขนาดใหญ่มาก ๆ

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

มันรวมประสิทธิภาพการทำงานของทั้งการวนซ้ำและการใช้การยกกำลังในขณะที่อ่านยาก ฉันไม่เห็นจุดนี้จริงๆ
สเปกตรัม

2
อย่าใช้มัน เป็นเพียงซีพียูที่ลูกค้าใช้เพื่อผู้ที่ใส่ใจ;)
ฟักซี่

2
@fiffy เอาล่ะลูกค้า CPU ก็มีค่าเช่นกันโดยเฉพาะบนมือถือและแอพพลิเคชั่นที่ซับซ้อน :)
Raito

5

ตามคำตอบของ coccoแต่ desugerified เล็กน้อย (ตรงไปตรงมาสิ่งที่ฉันรู้สึกสบายใจยังคงอยู่ / เพิ่ม) และไม่แสดงศูนย์ต่อท้าย แต่ยังสนับสนุน 0 หวังว่าจะเป็นประโยชน์สำหรับผู้อื่น:

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


4
1551859712 / 1024 = 1515488
1515488 / 1024 = 1479.96875
1479.96875 / 1024 = 1.44528198242188

ทางออกของคุณถูกต้อง สิ่งสำคัญที่ต้องตระหนักคือในการที่จะได้รับจาก1551859712ถึง1.5คุณต้องทำหารด้วย 1,000 แต่จำนวนไบต์จะถูกนับเป็นจำนวนไบนารีต่อทศนิยมที่ 1024 ดังนั้นทำไมค่า Gigabyte จึงน้อยกว่า


@Eli ... ใช่แล้วดูเหมือนว่า ฉันเดาว่าฉันคาดหวังว่า "1.5" ตั้งแต่ 1551859712 แต่นั่นหมายความว่าฉันอยู่ในรูปทศนิยมไม่ใช่เลขฐานสอง
Hristo

3

ฉันพบคำตอบของ @ cocco ที่น่าสนใจ แต่มีปัญหาดังต่อไปนี้:

  1. อย่าแก้ไขประเภทหรือประเภทเนทิฟที่คุณไม่ได้เป็นเจ้าของ
  2. เขียนโค้ดที่สะอาดและอ่านได้สำหรับมนุษย์ปล่อยให้ minifiers ปรับแต่งโค้ดสำหรับเครื่อง
  3. (โบนัสสำหรับผู้ใช้ TypeScript) เล่นได้ไม่ดีกับ TypeScript

typescript:

 /**
 * Describes manner by which a quantity of bytes will be formatted.
 */
enum ByteFormat {
  /**
   * Use Base 10 (1 kB = 1000 bytes). Recommended for sizes of files on disk, disk sizes, bandwidth.
   */
  SI = 0,
  /**
   * Use Base 2 (1 KiB = 1024 bytes). Recommended for RAM size, size of files on disk.
   */
  IEC = 1
}

/**
 * Returns a human-readable representation of a quantity of bytes in the most reasonable unit of magnitude.
 * @example
 * formatBytes(0) // returns "0 bytes"
 * formatBytes(1) // returns "1 byte"
 * formatBytes(1024, ByteFormat.IEC) // returns "1 KiB"
 * formatBytes(1024, ByteFormat.SI) // returns "1.02 kB"
 * @param size The size in bytes.
 * @param format Format using SI (Base 10) or IEC (Base 2). Defaults to SI.
 * @returns A string describing the bytes in the most reasonable unit of magnitude.
 */
function formatBytes(
  value: number,
  format: ByteFormat = ByteFormat.SI
) {
  const [multiple, k, suffix] = (format === ByteFormat.SI
    ? [1000, 'k', 'B']
    : [1024, 'K', 'iB']) as [number, string, string]
  // tslint:disable-next-line: no-bitwise
  const exp = (Math.log(value) / Math.log(multiple)) | 0
  // or, if you'd prefer not to use bitwise expressions or disabling tslint rules, remove the line above and use the following:
  // const exp = value === 0 ? 0 : Math.floor(Math.log(value) / Math.log(multiple)) 
  const size = Number((value / Math.pow(multiple, exp)).toFixed(2))
  return (
    size +
    ' ' +
    (exp 
       ? (k + 'MGTPEZY')[exp - 1] + suffix 
       : 'byte' + (size !== 1 ? 's' : ''))
  )
}

// example
[0, 1, 1024, Math.pow(1024, 2), Math.floor(Math.pow(1024, 2) * 2.34), Math.pow(1024, 3), Math.floor(Math.pow(1024, 3) * 892.2)].forEach(size => {
  console.log('Bytes: ' + size)
  console.log('SI size: ' + formatBytes(size))
  console.log('IEC size: ' + formatBytes(size, 1) + '\n')
});

1

นี่คือการปรับปรุงขนาดของคำตอบ mpen

function humanFileSize(bytes, si=false) {
  let u, b=bytes, t= si ? 1000 : 1024;     
  ['', si?'k':'K', ...'MGTPEZY'].find(x=> (u=x, b/=t, b**2<1));
  return `${u ? (t*b).toFixed(1) : bytes} ${u}${!si && u ? 'i':''}B`;    
}


0

สำหรับผู้ที่ใช้Angularมีแพคเกจที่เรียกangular-pipesว่ามีท่อสำหรับสิ่งนี้:

ไฟล์

import { BytesPipe } from 'angular-pipes';

การใช้

{{ 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 -->

เชื่อมโยงไปยังเอกสาร


0

คำตอบของฉันอาจจะสาย แต่ฉันคิดว่ามันจะช่วยใครซักคน

คำนำหน้าตัวชี้วัด:

/**
 * Format file size in metric prefix
 * @param fileSize
 * @returns {string}
 */
const formatFileSizeMetric = (fileSize) => {
  let size = Math.abs(fileSize);

  if (Number.isNaN(size)) {
    return 'Invalid file size';
  }

  if (size === 0) {
    return '0 bytes';
  }

  const units = ['bytes', 'kB', 'MB', 'GB', 'TB'];
  let quotient = Math.floor(Math.log10(size) / 3);
  quotient = quotient < units.length ? quotient : units.length - 1;
  size /= (1000 ** quotient);

  return `${+size.toFixed(2)} ${units[quotient]}`;
};

คำนำหน้าไบนารี:

/**
 * Format file size in binary prefix
 * @param fileSize
 * @returns {string}
 */
const formatFileSizeBinary = (fileSize) => {
  let size = Math.abs(fileSize);

  if (Number.isNaN(size)) {
    return 'Invalid file size';
  }

  if (size === 0) {
    return '0 bytes';
  }

  const units = ['bytes', 'kiB', 'MiB', 'GiB', 'TiB'];
  let quotient = Math.floor(Math.log2(size) / 10);
  quotient = quotient < units.length ? quotient : units.length - 1;
  size /= (1024 ** quotient);

  return `${+size.toFixed(2)} ${units[quotient]}`;
};

ตัวอย่าง:

// Metrics prefix
formatFileSizeMetric(0)      // 0 bytes
formatFileSizeMetric(-1)     // 1 bytes
formatFileSizeMetric(100)    // 100 bytes
formatFileSizeMetric(1000)   // 1 kB
formatFileSizeMetric(10**5)  // 10 kB
formatFileSizeMetric(10**6)  // 1 MB
formatFileSizeMetric(10**9)  // 1GB
formatFileSizeMetric(10**12) // 1 TB
formatFileSizeMetric(10**15) // 1000 TB

// Binary prefix
formatFileSizeBinary(0)     // 0 bytes
formatFileSizeBinary(-1)    // 1 bytes
formatFileSizeBinary(1024)  // 1 kiB
formatFileSizeBinary(2048)  // 2 kiB
formatFileSizeBinary(2**20) // 1 MiB
formatFileSizeBinary(2**30) // 1 GiB
formatFileSizeBinary(2**40) // 1 TiB
formatFileSizeBinary(2**50) // 1024 TiB

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.