Readable file sizes with the Twig templating system
Asked Answered
A

3

9

I'm wondering if there's a built in way to output readable file sizes with the Twig templating system. Say I have something like this in my template:

<p>This limit is currently set to {{ maxBytes }}</p>

How could I format maxBytes to display something like 30 GB?

Amatol answered 7/3, 2013 at 19:45 Comment(1)
To my knowledge there is no defined function/filter to do this. Your only solution is to extend twig.Romeliaromelle
B
29

There are a couple of ways you can go about accomplishing that:

1) get a Twig extension that will handle it for you. One like this one: https://github.com/BrazilianFriendsOfSymfony/BFOSTwigExtensionsBundle

Once enabled you would just do:

{{ maxBytes|bfos_format_bytes }}

And this will give you what you want.

2) You can create a macro that will do this if you dont want to add an entire extension. That would look something like this:

{% macro bytesToSize(bytes) %}
{% spaceless %}
    {% set kilobyte = 1024 %}
    {% set megabyte = kilobyte * 1024 %}
    {% set gigabyte = megabyte * 1024 %}
    {% set terabyte = gigabyte * 1024 %}

    {% if bytes < kilobyte %}
        {{ bytes ~ ' B' }}
    {% elseif bytes < megabyte %}
        {{ (bytes / kilobyte)|number_format(2, '.') ~ ' KiB' }}
    {% elseif bytes < gigabyte %}
        {{ (bytes / megabyte)|number_format(2, '.') ~ ' MiB' }}
    {% elseif bytes < terabyte %}
        {{ (bytes / gigabyte)|number_format(2, '.') ~ ' GiB' }}
    {% else %}
        {{ (bytes / terabyte)|number_format(2, '.') ~ ' TiB' }}
    {% endif %}
{% endspaceless %}
{% endmacro %}

You can read more about where to put and how to use the macros here: http://twig.sensiolabs.org/doc/tags/macro.html

Benefit answered 8/3, 2013 at 20:46 Comment(0)
P
17

Or, just create the twig extension:

ByteConversionTwigExtension.php

<?php
// src/AppBundle/Twig/Extension

namespace AppBundle\Twig\Extension;


class ByteConversionTwigExtension extends \Twig_Extension
{


    /**
     * Gets filters
     *
     * @return array
     */
    public function getFilters()
    {
        return array(
             new \Twig_SimpleFilter('format_bytes', array($this, 'formatBytes')),
        );
    }    

    public function getName()
    {
        return 'format_bytes';
    }

    function formatBytes($bytes, $precision = 2)
    {
        $units = array('B', 'KiB', 'MiB', 'GiB', 'TiB');
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);

        // Uncomment one of the following alternatives
         $bytes /= pow(1024, $pow);

        return round($bytes, $precision) . ' ' . $units[$pow];
    }

}

services.yml

parameters:
    app.byte_conversion_twig_extension.twig.extension.class: AppBundle\Twig\Extension\ByteConversionTwigExtension

services:
    app.byte_conversion.twig.extension:
        class: %app.byte_conversion_twig_extension.twig.extension.class%
        tags:
            - { name: twig.extension }  

Twig template:

{{ variable | format_bytes }}
Perceptible answered 30/5, 2016 at 10:50 Comment(3)
To read as OS does use 1000 (KiB MiB GiB TiB) instead of 1024Boastful
Be aware that KiB refers to KibiByte 1 KiB = 1024 B and KB refers to KiloByte as 1KB = 1000 Bytes. Kilo always stands for "times thousand" in international system unit. On the other hand, many software developers (even in well knonw OS) mix all theses units without any regard of the accepted definition.Apterous
Don't want to sound pedantic, but KB has no significance in the international system unit (or, Kelvin Bytes?). It should either be kB or KiB.Vannoy
N
3

A twig extension for human readable code using symfony 4 coding format and Jeffrey Sambells formatting function:

src/Twig/AppExtension.php

<?php

namespace App\Twig;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class AppExtension extends AbstractExtension
{
    /**
     * @var ContainerInterface
     */
    protected $container;


    /**
     * Constructor
     *
     * @param ContainerInterface $container
     */
    public function __construct(
        ContainerInterface $container
    )
    {
        $this->container = $container;
    }

    public function getFilters()
    {
        return array(
            new TwigFilter('formatBytes', array($this, 'formatBytes')),
        );
    }

    /**
     * @param $bytes
     * @param int $precision
     * @return string
     */
    public function formatBytes($bytes, $precision = 2)
    {
        $size = ['B','kB','MB','GB','TB','PB','EB','ZB','YB'];
        $factor = floor((strlen($bytes) - 1) / 3);
        return sprintf("%.{$precision}f", $bytes / pow(1024, $factor)) . @$size[$factor];
    }

}

services.yaml:

App\Twig\AppExtension:
    arguments:
        - '@service_container'
    tags:
        - { name: twig.extension}

usage in template:

{{ bytes| formatBytes }}
{{ bytes| formatBytes(0) }}
Newt answered 30/4, 2019 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.