Why use a hosted file service from Laravel
Your Laravel app can keep files on its own disk, or in a bucket it has to configure, secure and resize for. With Fileboy the app sends the file once, gets an ID back and keeps only that ID. Images are resized by changing a URL, so there is no image processing in your app, and the same ID works from any language.
1. Install the package
composer require fileboy/fileboyYou need a public key. Create a free app and copy it from the Keys page. Keep keys out of your code: read them from credentials or the environment.
2. Configure it once
use Fileboy\Client;
public function register(): void
{
$this->app->singleton(Client::class, fn () => new Client(
publicKey: config('services.fileboy.public_key'),
privateKey: config('services.fileboy.private_key'), // optional
));
}
// config/services.php
'fileboy' => [
'public_key' => env('FILEBOY_PUBLIC_KEY'),
'private_key' => env('FILEBOY_PRIVATE_KEY'),
],3. Upload and keep the ID
Pass the uploaded file through. The call returns the file's details, and the id is the only thing to store.
use Fileboy\Client;
use Fileboy\Exception\FileboyException;
use Illuminate\Http\Request;
class AvatarController extends Controller
{
public function store(Request $request, Client $fileboy)
{
$upload = $request->file('avatar');
try {
$file = $fileboy->uploadFile(
$upload->getRealPath(),
name: $upload->getClientOriginalName(),
mime: $upload->getMimeType(),
);
} catch (FileboyException $e) {
return back()->withErrors(['avatar' => $e->getMessage()]);
}
$request->user()->update(['avatar_fileboy_id' => $file->id]);
return back();
}
}Schema::table('users', function (Blueprint $table) {
$table->string('avatar_fileboy_id')->nullable();
});4. Show the image at the size you need
Build the URL from the stored ID. Asking for the size you display keeps pages light, and the original is never changed.
use Fileboy\Client;
public function avatarUrl(int $size = 96): ?string
{
if (! $this->avatar_fileboy_id) {
return null;
}
return app(Client::class)->buildImageUrl($this->avatar_fileboy_id, transforms: [
['type' => 'resize', 'width' => $size * 2, 'height' => $size * 2, 'fit' => 'cover'],
['type' => 'format', 'format' => 'webp'],
]);
}Reading a file or image needs no key, so these URLs work in <img> tags, emails and anywhere else, unless the app requires signed URLs. Uploads are what your key authorises.
Checked against the current libraries in November 2026. Found something that no longer works? Tell us.