Display pdf file from local disk in Laravel 5?

2020-03-04 03:57发布

问题:

I have a Laravel 5.5 app where users with administrator privileges can upload files. After they upload the files I'd like them to be able to view the file in the administrator dashboard.

I have a DocumentController.php that handles the file upload to the local disk:

public function store(Request $request)
{
    // check to make sure user is an admin
    $request->user()->authorizeRoles('admin');

    // validate that the document is a pdf and 
    // that required fields are filled out
    $this->validate($request, [
        'title' => 'required',
        'description' => 'required',
        'user_id' => 'required|exists:users,id', 
        'document_path' => 'required|mimes:pdf'
    ]);

    $file = $request->file('document_path');

    $path = $file->store('documents/' . $request->user_id);

    $document = Document::create([
        'user_id' => $request->user_id,
        'title' => $request->title,
        'description' => $request->description,
        'file_path' => $path
    ]);

    return redirect($document->path());
} 

This method takes the file from the form, makes sure it is a pdf and then saves the file to storage/app/documents/{user_id}. It then creates a Document record in the database and forwards to the URL based on the document id: /admin/document/{ $document->id }

That route is defined as Route::get('/admin/document/{document}', 'DocumentController@show');

Where in the controller I pass the document to the view:

public function show(Document $document, Request $request)
{
    // check to make sure user is an admin
    $request->user()->authorizeRoles('admin');

    $storagePath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix();

    return view('admin.document', compact('document', 'storagePath'));
}

On that page I would like to display the pdf document.

resources/views/admin/document.blade.php

@extends('layouts.app')

@section('content')
<div class='container'>
    <div class='row'>
        <div class='col-sm-2'>
            <a href='/admin'>< Back to admin</a>
        </div>
        <div class='col-sm-8'>
            {{ $document }}

            <embed src="{{ Storage::url($document->file_path) }}" style="width:600px; height:800px;" frameborder="0">

        </div>
    </div>
</div>
@endsection

I have tried using the $storagePath variable and Storage methods but cannot get the pdf file to display within the iframe.

Using local file storage how would I display the file in the browser? Also, I've protected the route so that only admins can view the document's page but what is the best way to secure the path to the document itself?

回答1:

If you want your files to be protected (only admin can access them), then you need to create a new route and new DocumentController method getDocument

Add new route

Route::get('documents/pdf-document/{id}', 'DocumentController@getDocument');

In DocumentController, add

use Storage;
use Response;

Add new method that will read your pdf file from the storage and return it back

public function getDocument($id)
{
    $document = Document::findOrFail($id);

    $filePath = $document->file_path;

    // file not found
    if( ! Storage::exists($filePath) ) {
      abort(404);
    }

    $pdfContent = Storage::get($filePath);

    // for pdf, it will be 'application/pdf'
    $type       = Storage::mimeType($filePath);
    $fileName   = Storage::name($filePath);

    return Response::make($pdfContent, 200, [
      'Content-Type'        => $type,
      'Content-Disposition' => 'inline; filename="'.$fileName.'"'
    ]);
}

In your view you can show the document like this

<embed
    src="{{ action('DocumentController@getDocument', ['id'=> $document->id]) }}"
    style="width:600px; height:800px;"
    frameborder="0"
>


回答2:

Shorter version of that Response::make() from @ljubadr answer:

return Storage::response($document->file_path)



回答3:

<embed
src="{{ url('/filepath') }}"
style="width:600px; height:800px;"
frameborder="0">