Головне правило - не тримати файл цілком у пам'яті PHP. Storage::get() на файлі в 2 ГБ упреться в memory_limit.
Запис потоком:
Storage::disk('s3')->putFile('videos', $request->file('video')); // потоком, а не get/put
Storage::disk('s3')->writeStream('backup.sql.gz', fopen($path, 'r'));
putFile() і putFileAs() передають файл потоком самі.
Читання потоком:
$stream = Storage::disk('s3')->readStream('exports/big.csv');
while (($line = fgets($stream)) !== false) { /* ... */ }
Віддача користувачу:
// згенерований на льоту файл - без запису на диск
return response()->streamDownload(function () {
$out = fopen('php://output', 'w');
Order::query()->lazyById(1000)->each(fn ($o) => fputcsv($out, [$o->id, $o->total]));
fclose($out);
}, 'orders.csv');
// готовий файл у S3 - краще посилання, ніж проксі через PHP
return redirect(Storage::disk('s3')->temporaryUrl($path, now()->plus(minutes: 5)));
Що ще допомагає:
- важку обробку (конвертація відео, архівування) - у чергу, з окремим воркером і більшим таймаутом;
- завантаження великих файлів від клієнтів - напряму в сховище (
temporaryUploadUrl()); - для
localу Nginx -X-Accel-Redirect, щоб файл віддавав вебсервер, а PHP лише перевіряв права.