Herunterladen von Laravel Speicher ohne be-ganze Datei in Speicher
Bin ich mit Laravel Speicher und ich möchte, um zu dienen einige Benutzer (größer als memory-limit) - Dateien. Mein code wurde inspiriert von einem post in SO und es geht so:
$fs = Storage::getDriver();
$stream = $fs->readStream($file->path);
return response()->stream(
function() use($stream) {
fpassthru($stream);
},
200,
[
'Content-Type' => $file->mime,
'Content-disposition' => 'attachment; filename="'.$file->original_name.'"',
]);
Unfourtunately, ich Laufe in einen Fehler, der für große Dateien:
[2016-04-21 13:37:13] production.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Allowed memory size of 134217728 bytes exhausted (tried to allocate 201740288 bytes)' in /path/app/Http/Controllers/FileController.php:131
Stack trace:
#0 /path/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(133): Symfony\Component\Debug\Exception\FatalErrorException->__construct()
#1 /path/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(118): Illuminate\Foundation\Bootstrap\HandleExceptions->fatalExceptionFromError()
#2 /path/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(0): Illuminate\Foundation\Bootstrap\HandleExceptions->handleShutdown()
#3 /path/app/Http/Controllers/FileController.php(131): fpassthru()
#4 /path/vendor/symfony/http-foundation/StreamedResponse.php(95): App\Http\Controllers\FileController->App\Http\Controllers\{closure}()
#5 /path/vendor/symfony/http-foundation/StreamedResponse.php(95): call_user_func:{/path/vendor/symfony/http-foundation/StreamedResponse.php:95}()
#6 /path/vendor/symfony/http-foundation/Response.php(370): Symfony\Component\HttpFoundation\StreamedResponse->sendContent()
#7 /path/public/index.php(56): Symfony\Component\HttpFoundation\Response->send()
#8 /path/public/index.php(0): {main}()
#9 {main}
Es scheint, dass er versucht, zum laden der Datei in den Speicher. Ich hatte erwartet, dass die Nutzung von Strom und passthru würde dies nicht tun... Ist es, etwas fehlt in meinem code? Muss ich irgendwie angeben, chunk size oder was?
Den Versionen, die ich verwende, sind Laravel 5.1 und PHP 5.6.
- Das einzige Szenario, ich kann mir denken, wo
fpassthru
weist in den Speicher bei der Verwendung von output buffering. Sie könnten daher versuchen, eine Schleife auffread
mit einemecho
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Scheint es, dass die Ausgabe-Pufferung ist noch im Aufbau, bis eine Menge Speicher.
Versuchen Sie, ob vor dem fpassthru:
Könnte es sein, dass es mehrere Ausgabe-Puffer aktiv, dass ist der Grund, warum die während benötigt wird.
Stattdessen laden die gesamte Datei in den Speicher, auf einmal, versuchen Sie es mit fread Lesen und senden es werden chunk für chunk.
Hier ist ein sehr guter Artikel: http://zinoui.com/blog/download-large-files-with-php
Update
Einen einfacheren Weg, dies zu tun: rufen Sie einfach
vor der Rückgabe einer Antwort.
Kredit @Christiaan
fpassthru
resultierte in genau den gleichen Fehler. Mit dieser Methode bin ich in der Lage, um die Datei herunterzuladen.if (ob_get_level()) ob_end_clean();
vor der Rückgabe einer Antwort. Ich werde aktualisieren Sie die Antwort und geben Kredite an SieX-Send-File
.X-Send-File
ist eine interne Richtlinie, die Varianten für Apache, nginx und lighthttpd. Es ermöglicht Ihnen, die komplett überspringen Verteilung einer Datei über PHP und ist eine Anweisung, die sagt dem webserver, was zum senden als Antwort anstatt der eigentlichen Antwort von FastCGI.Ich habe das Problem gelöst, bevor Sie auf ein persönliches Projekt und wenn Sie wollen, um zu sehen, die Summe meiner Arbeit, Sie können es hier:
https://github.com/infinity-next/infinity-next/blob/master/app/Http/Controllers/Content/ImageController.php#L250-L450
Diese beschäftigt sich nicht nur mit der Verteilung von Dateien, aber die Handhabung von streaming-Medien zu suchen. Sie sind frei, diesen code.
Hier ist die offizielle Apache-Dokumentation auf
X-Send-File
.https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
Du tun haben zu Bearbeiten Sie Ihre webserver und markieren Sie bestimmte Verzeichnisse als interne für nginx zu erfüllen
X-Send-File
Richtlinien.Habe ich Beispiel-Konfiguration für Apache und nginx sind für meinen obigen code hier ein.
https://github.com/infinity-next/infinity-next/wiki/Installation
Dies wurde getestet auf high-traffic-websites. Tun nicht Puffer Medien über einen PHP-Daemon, es sei denn, Ihre Website ist kein Verkehr, oder du bist Blutungen Ressourcen.
X-Send-File
fügt Risiken der Freilegung der Datei an nicht autorisierte clients?Könnten Sie versuchen, mit dem StreamedResponse Komponente direkt, anstelle des Laravel-wrapper dafür. StreamedResponse