Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Human Readable File Size Laravel Package

codeinc/human-readable-file-size

Convert raw byte values into clean, human-readable file size strings with this lightweight PHP package. Configurable precision, units, and formatting make it easy to show sizes like 1.5 MB anywhere, and it works seamlessly in Laravel or any PHP project.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require codeinc/human-readable-file-size

This is a zero-dependency, single-purpose library: it turns an integer byte count into a short string like 1.18 MB. There is no service provider, no facade, and no config file — Laravel's package discovery has nothing to register. The entire surface area is one namespaced function, so the first thing to do after install is open vendor/codeinc/human-readable-file-size/src/ and read the signature (it is a handful of lines). Note the namespace import style:

use function CodeInc\HumanReadableFileSize\humanReadableFileSize;

echo humanReadableFileSize(1234567);        // "1.18 MB"
echo humanReadableFileSize(1234567, 0);     // "1 MB"

Your first real use case is almost always the same: a file upload or a media library where the database stores size in bytes but every human-facing surface (Blade view, JSON resource, error message, Artisan output) needs something readable. Wire it up once in a model accessor and you are done:

// app/Models/Upload.php
use function CodeInc\HumanReadableFileSize\humanReadableFileSize;

protected function sizeHuman(): Attribute
{
    return Attribute::get(fn () => humanReadableFileSize($this->size));
}
<td>{{ $upload->size_human }}</td>

If you are on Laravel 11+, stop here and compare against Illuminate\Support\Number::fileSize($bytes), which ships in the framework, respects locale, and needs no third-party dependency. This package only earns its place if you are pinned to Laravel 10 or older, or you want the exact output format it produces.

Implementation Patterns

Wrap it, don't scatter it. Because the package exposes a global function, calling it directly from fifty Blade templates makes the format impossible to change and awkward to mock. Put a thin boundary around it:

// app/Support/FileSize.php
namespace App\Support;

use function CodeInc\HumanReadableFileSize\humanReadableFileSize;

class FileSize
{
    public static function format(?int $bytes, int $precision = 2): string
    {
        if ($bytes === null) {
            return '—';
        }

        return humanReadableFileSize(max(0, $bytes), $precision);
    }
}

Now a future swap to Number::fileSize(), a locale-aware formatter, or a test double is a one-line change.

API Resources. Keep raw bytes in the payload for machines and add the label alongside; never ship only the string:

public function toArray($request): array
{
    return [
        'size'       => $this->size,               // 1234567
        'size_human' => FileSize::format($this->size), // "1.18 MB"
    ];
}

Sorting, filtering, and "files larger than 10 MB" queries must always run against the integer column. Human-readable strings sort lexicographically (9 KB > 10 KB), which is a bug waiting to happen.

Validation and error messages. This is where the library is genuinely nicer than raw bytes. Laravel's max: rule on uploads is expressed in kilobytes, but the message users see should match what they picked:

$limitBytes = 10 * 1024 * 1024;

$request->validate([
    'file' => ['required', 'file', 'max:' . ($limitBytes / 1024)],
], [
    'file.max' => 'The file must be smaller than ' . FileSize::format($limitBytes, 0) . '.',
]);

Artisan and log output. Commands that report on storage, exports, or cache dumps read much better with FileSize::format(Storage::disk('s3')->size($path)) than with a nine-digit number.

Collections. ->map(fn ($f) => FileSize::format($f->size)) works fine, but if you are formatting the same model repeatedly in one request, cache the accessor result on the instance rather than recomputing in a loop over thousands of rows.

Gotchas and Tips

  • It is a function, not a class. You must use function ..., and any code sniffing or IDE that does not understand function imports will flag it. There is no HumanReadableFileSize::format() static to fall back on in older tags — verify against the source before assuming an API shape.
  • Binary vs. decimal prefixes. The library's base (1024 vs. 1000) determines whether 1 MB means 1,048,576 bytes or 1,000,000. This is the single most common source of "the number is wrong" bug reports, because PHP's own upload_max_filesize and post_max_size are binary but labelled as MB. Compute your limits in bytes, format with the same library, and never mix the two.
  • Null, zero, and negative input. A missing or unsized file yields null, and 0 formats to something like 0 B. Guard at the boundary (as in the wrapper above) rather than in every view. Negative values should never reach the formatter.
  • Locale. Expect a . decimal separator and English suffixes. If the app is localised, this package will look out of place next to translated validation messages — another argument for Laravel's Number::fileSize(), which takes a locale.
  • Precision is not "significant digits". Passing 2 gives at most two decimals, and you will see 1.00 KB for values that would be more naturally shown as 1 KB. Tune per-context (list views: 0–1 decimals; detail views: 2) rather than globally.
  • Maintenance risk. Last release was August 2023, there are zero dependents, and the scope is small enough that you could vendor the logic into app/Support in five minutes. For a package this trivial, copying it removes a supply-chain dependency with essentially no downside.
  • Test the exact strings. Assertions like assertSame('1.18 MB', ...) are brittle across precision and base changes but are exactly what you want if the output is user-facing. Pin the expected strings in a unit test around your wrapper, not around the vendor call, so an upgrade that changes formatting fails loudly in one place.
  • Extension point is the wrapper. Do not fork the vendor directory. If you need SI suffixes, thousands separators, or a KB→Ko translation, do it in App\Support\FileSize and leave the dependency untouched.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json