Number::fileSize
Converts a byte count into a readable size string such as 1 KB or 2.5 MB.
Number::fileSize(int|float $bytes, int $precision = 0, ?int $maxPrecision = null): string- Added in Laravel 10.33.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$$bytes | int|float | The size in bytes. Negative values are stepped down by magnitude and keep their sign. |
$$precisionoptional | int= 0 | Exact fraction digits, padded with zeros. |
$$maxPrecisionoptional | ?int= null | Upper bound on fraction digits. Takes priority over $precision. |
Return value
stringThe size and its unit separated by a space, for example '1 KB' or '2.50 MB'.
Errors
Throws RuntimeException when the intl PHP extension is not loaded, because the number itself is rendered by Number::format().
Changelog
- PHP 10.33.0Introduced together with the Illuminate\Support\Number class.
- PHP 12.60.0Negative byte values now step through the units correctly instead of stopping at B.
Number::fileSize() walks the byte count down through B, KB, MB, GB, TB, PB, EB, ZB, YB, dividing by 1024 each step, and hands the remaining mantissa to Number::format(). Use it for upload limits, attachment sizes, cache and disk reports — anywhere a raw filesize() result would reach a human.
Binary steps, decimal labels
The divisor is 1024 but the units are written KB and MB, not KiB and MiB. That is the same convention most operating systems use, and it means the string will not agree with a disk vendor's marketing figure. If your audience needs strict IEC units you will have to build the string yourself.
The step threshold is 0.9, not 1
The loop advances while abs($bytes) / 1024 > 0.9, so anything from about 922 bytes upward is already promoted to KB. Number::fileSize(1000) returns 1 KB, not 1000 B. This keeps awkward strings like 1000 B off the screen but does mean the number you see can be below 1.
Despite doing the unit maths in plain PHP, this method still requires intl — the formatting call at the end is Number::format().
Example
When to use it
- Showing an attachment's size next to its download link
- Rendering an upload limit in a validation error message
- Summarising per-user disk consumption in an admin table
Frequently asked questions
Does Number::fileSize use 1000 or 1024 bytes per kilobyte?
1024, but it labels the result KB and MB rather than KiB and MiB. That matches most operating systems and file managers, and disagrees with drive manufacturers' decimal figures.
Why does 1000 bytes show as 1 KB instead of 1000 B?
The unit loop advances whenever the value divided by 1024 exceeds 0.9, so 922 bytes and above are already promoted to KB. With the default precision of 0, the resulting 0.98 rounds to 1.
Does Number::fileSize work without the intl extension?
No. It does the unit maths itself but formats the final number with Number::format(), which builds a NumberFormatter and throws RuntimeException when intl is missing.
More examples
Where each unit takes over
921 bytes still prints as 921 B but 922 flips to KB, because the loop advances at a ratio above 0.9 rather than 1.0. The maxPrecision column shows the underlying fraction — 0.9 KB — that the default precision of 0 rounds away to 1 KB.
<?php
use Illuminate\Support\Number;
$sizes = [0, 512, 921, 922, 1024, 1048576, 1073741824, 1099511627776];
foreach ($sizes as $bytes) {
printf("%-16s %-10s %s\n", $bytes, Number::fileSize($bytes), Number::fileSize($bytes, maxPrecision: 2));
}Formatting an uploaded file
The raw byte count is kept in the payload for sorting and comparison while the formatted string is only for display. Never sort a table on the formatted value — '9 KB' and '10 MB' compare as strings in the wrong order.
<?php
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Number;
class AttachmentController
{
public function show(string $path): array
{
$bytes = Storage::disk('public')->size($path);
return [
'path' => $path,
'bytes' => $bytes,
'size' => Number::fileSize($bytes, maxPrecision: 1),
];
}
}Validation message with a limit
Prints 'The avatar may not be larger than 2 MB.' Deriving the message from the same constant as the rule keeps them from drifting apart, which is the usual reason an error message quotes a limit the validator does not actually enforce.
<?php
use Illuminate\Support\Number;
$maxKilobytes = 2048; // Laravel's max: rule counts kilobytes
$limit = Number::fileSize($maxKilobytes * 1024);
$rules = ['avatar' => "required|image|max:{$maxKilobytes}"];
$messages = ['avatar.max' => "The avatar may not be larger than {$limit}."];
echo $messages['avatar.max'], PHP_EOL;
Discussion