web-dev-qa-db-fra.com

Laravel 5 téléchargements de fichiers: stream () ou download ()

J'ai une application Laravel 5.4 où les utilisateurs authentifiés doivent pouvoir télécharger des fichiers privés à partir du stockage S3. J'ai configuré une route et un contrôleur pour autoriser les téléchargements de fichiers privés.

Le code ressemble à ceci:

Route:

Route::get('file/{filename}', 'FileController@download')->where(['filename' => '[A-Za-z0-9-._\/]+'])->name('file')->middleware('auth:employee');

Manette:

public function download($fileName)
{
    if (!$fileName || !Storage::exists($fileName)) {
        abort(404);
    }

    return response()->stream(function() use ($fileName) {
        $stream = Storage::readStream($fileName);
        fpassthru($stream);
        if (is_resource($stream)) {
            fclose($stream);
        }
    }, 200, [
        'Cache-Control'         => 'must-revalidate, post-check=0, pre-check=0',
        'Content-Type'          => Storage::mimeType($fileName),
        'Content-Length'        => Storage::size($fileName),
        'Content-Disposition'   => 'attachment; filename="' . basename($fileName) . '"',
        'Pragma'                => 'public',
    ]);
}

Tout fonctionnait bien, mais quand j'ai regardé de plus près les documents Laravel , j'ai trouvé qu'ils parlaient simplement de response()->download().

Si j'implémente ce type de réponse, mon code ressemblerait à ceci:

public function download($fileName)
{
    if (!$fileName || !Storage::exists($fileName)) {
        abort(404);
    }

    $file = Storage::get($fileName);

    return response()->download($file, $fileName, [
        'Content-Type'  => Storage::mimeType($fileName),
    ]);
}

Les deux fonctions peuvent être trouvées dans le documentation API .

Ma question: quelle serait la voie à suivre préférée et quels sont les avantages/inconvénients de chacun?

D'après ce que j'ai rassemblé jusqu'à présent:

Stream:

  • Ne nécessite pas que le fichier entier soit chargé en mémoire
  • Convient aux gros fichiers

Télécharger:

  • Nécessite moins de code
15
Jones03

Lorsque vous appelez Laravel l'assistant response(), il renvoie une instance de Illuminate\Routing\ResponseFactory. ResponseFactory a ces deux méthodes: download et stream - les deux méthodes en question. Si vous creusez un peu plus profondément, vous verrez que download renvoie une instance de \Symfony\Component\HttpFoundation\BinaryFileResponse, tandis que stream renvoie un \Symfony\Component\HttpFoundation\StreamedResponse - ce sont les deux composants Symfony.

Il n'est pas nécessaire de fouiller dans le code ici, mais il est agréable d'avoir une compréhension de ce qui se passe sous le capot. Maintenant que nous savons que les objets sous-jacents renvoyés proviennent du composant HTTP Symfony, nous pouvons consulter les documents Symfony et voir ce qu'ils recommandent d'utiliser. En règle générale, les flux sont utilisés lorsque la taille du fichier est inconnue, par exemple lorsque vous générez le fichier à la volée. Dans la plupart des autres cas, la BinaryFileResponse générée par la méthode download sera suffisante pour vos besoins.

Vous pouvez jeter un oeil à une explication beaucoup plus approfondie du streaming HTTP et de ses cas d'utilisation ici .

9
samrap