Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Angular2 + TypeScript file size Pipe/Filter. Convert bytes into largest possible unit. e.g. 1024 => 1 KB
/**
* @license
* Copyright (c) 2019 Jonathan Catmull.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import { Pipe, PipeTransform } from '@angular/core';
/*
* Convert bytes into largest possible unit.
* Takes an precision argument that defaults to 2.
* Usage:
* bytes | fileSize:precision
* Example:
* {{ 1024 | fileSize}}
* formats to: 1 KB
*/
@Pipe({name: 'fileSize'})
export class FileSizePipe implements PipeTransform {
private units = [
'bytes',
'KB',
'MB',
'GB',
'TB',
'PB'
];
transform(bytes: number = 0, precision: number = 2 ) : string {
if ( isNaN( parseFloat( String(bytes) )) || ! isFinite( bytes ) ) return '?';
let unit = 0;
while ( bytes >= 1024 ) {
bytes /= 1024;
unit ++;
}
return bytes.toFixed( + precision ) + ' ' + this.units[ unit ];
}
}
@bardiarastin

This comment has been minimized.

Copy link

commented Nov 6, 2016

ERROR in [default] file-size.pipe.ts:16:28
Argument of type 'number' is not assignable to parameter of type 'string'.

since you are declaring bytes as a number , you can not pass it to parseFloat() so the code won't work .

the correct way is :

transform(bytes: number = 0, precision: number = 2 ) : string { if (!isFinite( bytes ) ){ return '?'; } let unit = 0; while ( bytes >= 1024 ) { bytes /= 1024; unit ++; }

@JonCatmull

This comment has been minimized.

Copy link
Owner Author

commented Nov 23, 2016

@bardiarastin Thanks for you comment, I have updated my code to fix the TypeScript compiler error you mentioned.

@coreyog

This comment has been minimized.

Copy link

commented Feb 24, 2017

A simple suggestion. if (unit == 0) precision = 0; after the while loop so you don't end up with "38.00 bytes."

I guess this wouldn't help if you were averaging file sizes or something but I bet total file size is it's more popular use.

@laverix

This comment has been minimized.

Copy link

commented Mar 16, 2017

Thanks

@crazyredd

This comment has been minimized.

Copy link

commented Feb 25, 2018

Still works like a charm, thanks for saving me the headache

@AarjavP

This comment has been minimized.

Copy link

commented Mar 18, 2018

just a minor note, KB might be interpreted as kilobyte which equals 1000 bytes, instead of the kibibyte (KiB) which equals 1024 bytes.

@donmccurdy

This comment has been minimized.

Copy link

commented Apr 23, 2018

@JonCatmull this is a helpful filter! Would you mind putting a license header (MIT, Apache, ...) on it for reuse?

@RogierVC

This comment has been minimized.

Copy link

commented Oct 29, 2018

Excellent. Thank you!

@dsalguerot

This comment has been minimized.

Copy link

commented Oct 29, 2018

Thank you!

@ianstew12

This comment has been minimized.

Copy link

commented Mar 29, 2019

Could someone explain the purpose of a bytes pipe to a junior dev? I'm finding code examples but not a good summary of when it would be needed. I understand what bytes and pipes are but I don't know the purpose of a bytes pipe. Appreciate any help.

@Steph0

This comment has been minimized.

Copy link

commented Apr 16, 2019

Could someone explain the purpose of a bytes pipe to a junior dev?

  • Bytes is the smallest unit you can have for a file. By using the smallest you are sure you can easily convert to all the upper ones
  • Pipes allow to transform a data value to another "display" state in your templates (example: if your number is will a lot of decimals like 1.66666666666, you would probably prefer to round it for the user on the screen to 1.66; in that case pipes are usefull. There are of course more advantages, like changing the "display" data without changing the original value in your application logic if your pipe is pure and it should be), cf. https://angular.io/guide/pipes
  • So using bytes as base unit you can show to the user a human readable value of a file on the user screen (that is the pipe job)
  • Cherry on the top, if you want to format several bytes values accross your application, you can reuse your pipe everywhere in your templates (DRY, efficient, predictable, and easily testable if your pipe is pure), what could we ask more?

Another example would be dates. If you have different time formats of dates in your app logic it is often a nightmare and it is bug-prone. So in your application logic you stick to one date format (ISO, UTC, whatever) and on your user screen you use pipes like DatePipe to show the final "display" value of a date. Many formats for the user (pipes), but in the background one format to rule them all (ISO, UTC, whatever).

@msteini82

This comment has been minimized.

Copy link

commented Aug 24, 2019

Thank you for this great piece of code 😊👍

I just optimized it a little bit for me by adding the standard decimal pipe to convert the number to local format, so it looks better on my German project 😉

https://gist.github.com/msteini82/6b77f92feda1f6f8286bc1bc7e6fd21b

@JonCatmull

This comment has been minimized.

Copy link
Owner Author

commented Aug 28, 2019

Thanks, everyone for your comments! Sorry, I haven't been on here and the emails got overlooked.

@coreyog, @AarjavP, @donmccurdy, @msteini82

Thank you for your suggestions, I will definitely look to incorporate these and repost. Then perhaps this is worth putting in an npm module to easily import into your projects if anyone has a suggestion on the name then drop a comment below.

Thanks, again.

@MacGyver98

This comment has been minimized.

Copy link

commented Oct 3, 2019

A simple suggestion. if (unit == 0) precision = 0; after the while loop so you don't end up with "38.00 bytes."

I guess this wouldn't help if you were averaging file sizes or something but I bet total file size is it's more popular use.

And what about this one...

let unit = 0, division = bytes;
    
    while ( division >= 1024 ) {
      division /= 1024;
      unit ++;
    }
    if (bytes % 1024 <= 10) precision = 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.