web-dev-qa-db-fra.com

Laravel - affiche un PDF fichier en stockage sans forcer le téléchargement?

J'ai un fichier PDF stocké dans app/storage/et je veux que les utilisateurs authentifiés puissent voir ce fichier. Je sais que je peux les faire télécharger à l'aide de 

return Response::download($path, $filename, $headers);

mais je me demandais s’il était possible de leur faire afficher le fichier directement dans le navigateur, par exemple lorsqu’ils utilisent Google Chrome avec le visualiseur intégré PDF. Toute aide serait appréciée!

32
Luis Aceituno

Mise à jour pour 2017

A partir de Laravel 5.2, documenté sous Autres types de réponses vous pouvez maintenant utiliser l'assistant de fichier pour afficher un fichier dans le navigateur de l'utilisateur.

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

Source/merci de répondre ci-dessous

Réponse périmée de 2014

Il vous suffit d’envoyer le contenu du fichier au navigateur et de lui indiquer le type de contenu plutôt que d’indiquer au navigateur de le télécharger.

$filename = 'test.pdf';
$path = storage_path($filename);

return Response::make(file_get_contents($path), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'inline; filename="'.$filename.'"'
]);

Si vous utilisez Response::download, Content-Disposition est automatiquement mis en pièce jointe, ce qui permet au navigateur de le télécharger. Voir cette question pour les différences entre Content-Disposition inline et Attach.

Modifier: conformément à la demande dans les commentaires, je dois signaler que vous devez use Response au début de votre fichier pour utiliser la façade.

use Response;

Ou l'espace de nom complet si Response n'est pas associé à la façade de réponse d'Illuminate.

65
Ben Swinburne

Depuis Laravel 5.2, vous pouvez utiliser Réponses au fichier
En gros, vous pouvez l'appeler comme ceci:

return response()->file($pathToFile);

et il affichera les fichiers sous la forme PDF et les images en ligne dans le navigateur.

18
MegaCookie

Dans Laravel 5.5 vous pouvez simplement passer " inline " en tant que paramètre disposition de la fonction de téléchargement:

return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline');
6
Adam Albright

La réponse de Ben Swinburne est absolument correcte - il mérite les points! Pour moi, cependant, la réponse laisse un peu à désirer dans Laravel 5.1 qui m’a amené à faire des recherches - et dans 5.2 (qui a inspiré cette réponse), il existe un nouveau moyen de le faire rapidement.

Remarque: cette réponse contient des astuces pour prendre en charge les noms de fichiers UTF-8, mais il est recommandé de prendre en compte le support multiplateforme!

Dans Laravel 5.2, vous pouvez maintenant faire ceci:

$pathToFile = '/documents/filename.pdf'; // or txt etc.

// when the file name (display name) is decided by the name in storage,
// remember to make sure your server can store your file name characters in the first place (!)
// then encode to respect RFC 6266 on output through content-disposition
$fileNameFromStorage = rawurlencode(basename($pathToFile));

// otherwise, if the file in storage has a hashed file name (recommended)
// and the display name comes from your DB and will tend to be UTF-8
// encode to respect RFC 6266 on output through content-disposition
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf');

// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
return response()->file(storage_path($pathToFile), [
    'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"),
    'Content-Type'        => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc.
]);

Et dans Laravel 5.1, vous pouvez ajouter la méthode ci-dessus response()->file() comme solution de secours via un fournisseur de services avec une macro de réponse dans la méthode de démarrage (assurez-vous de l'enregistrer en utilisant son espace de noms dans config/app.php si vous en faites une classe). Contenu de la méthode de démarrage:

// Be aware that I excluded the Storage::exists() and / or try{}catch(){}
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) {

    // Storage facade path is relative to the root directory
    // Defined as "storage/app" in your configuration by default
    // Remember to import Illuminate\Support\Facades\Storage
    $storagePath         = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration
    $fileContents        = Storage::get($storagePath);
    $fileMimeType        = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc.
    $fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension

    $headers = array_merge([
        'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"),
        'Content-Length'      => strlen($fileContents), // mb_strlen() in some cases?
        'Content-Type'        => $fileMimeType,
    ], $userHeaders);

    return $factory->make($fileContents, 200, $headers);
});

Certains d'entre vous n'aiment pas les façades Laravel ou les méthodes d'assistance, mais ce choix vous appartient. Cela devrait vous donner des indications si la réponse de Ben Swinburne ne fonctionne pas pour vous.

Note d'opinion: Vous ne devriez pas stocker de fichiers dans une base de données. Néanmoins, cette réponse ne fonctionnera que si vous supprimez les éléments de façade Storage, en prenant le contenu au lieu du chemin comme premier paramètre, comme avec la réponse @BenSwinburne.

3
AARTT

J'utilise Laravel 5.4 et response()->file('path/to/file.ext') pour ouvrir, par exemple. un pdf en mode en ligne dans les navigateurs. Cela fonctionne assez bien, mais lorsqu'un utilisateur veut enregistrer le fichier, la boîte de dialogue de sauvegarde suggère la dernière partie de l'URL comme nom de fichier.

J'ai déjà essayé d'ajouter un tableau d'en-têtes comme mentionné dans Laravel-docs, mais cela ne semble pas écraser l'en-tête défini par la méthode file ():

return response()->file('path/to/file.ext', [
  'Content-Disposition' => 'inline; filename="'. $fileNameFromDb .'"'
]);
3
kreilinger

A partir de laravel 5.5 si le fichier est stocké sur un stockage distant

return Storage::response($path_to_file);

ou s'il est stocké localement, vous pouvez également utiliser

return response()->file($path_to_file);

Je recommanderais d'utiliser la façade de stockage.

2
Mihai Crăiță

La réponse de Ben Swinburne a été très utile.

Le code ci-dessous est pour ceux qui ont leur fichier PDF dans la base de données comme moi. 

$pdf = DB::table('exportfiles')->select('pdf')->where('user_id', $user_id)->first();

return Response::make(base64_decode( $pdf->pdf), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);

$pdf->pdf est la colonne du fichier dans la base de données.

2
Diamond

Dans laravel, liez votre dossier de stockage au dossier public avec la commande

php stockage artisanal: lien

Si vous avez déjà lié votre dossier public, utilisez la balise d'ancrage comme ci-dessous.

<a  href="{{ asset('/storage/otherFolderIfHave/filenameWithExt') }}" >View</a>
0
Miraj Khandaker