ST80
ST80

Reputation: 3893

PHP Laravel How to get original pdf file name and make it downloadable

I want to make a page in my laravel-application, where it should be possible to download a bunch of PDF-files. I've created a Model and a Controller, and within my Nova backend, I have uploaded some pdf-files.

My Nova fields:

public function fields(Request $request) {
   return [
      Text::make('File name', 'file_name')
        ->rules('required'),

      File::make('Download', 'file')
        ->disk('public')
        ->path('materials')
        ->storeOriginalName('file_original_name')
        ->storeSize('file_size')
        ->prunable(),
   ];
}

Then my model:

class Material extends Model {
   protected $fillable = [
    'file_name', 'file', 'file_original_name', 'file_size'
   ];
}

and my Controller:

use App\Material;
use Illuminate\Http\Request;

class MaterialController extends Controller {
  public function files()
   {
      $files = Material::get();
      return view('app.materials', compact('files'));
   }
}

In my web.php, I do this:

Route::get('materials', 'MaterialController@files')->name('materials');

In my blade view:

@foreach ($files as $file)
   <a href="{{ asset('storage/'. $file->file) }}" download>{{ $file->file_name }}</a>
@endforeach

So far this works, BUT when the orginal filename for example is 'myfile.pdf', $file->file returns something like 'dadjafmdahdyda2e23as.pdf', but I want the original name for the download.

How can I achieve that?

Upvotes: 1

Views: 2737

Answers (1)

apokryfos
apokryfos

Reputation: 40653

The download property according to MDN can be used in two ways:

  1. Without a value, in which case the filename is determined by :

    The Content-Disposition HTTP header
    The final segment in the URL path
    The media type (from the Content-Type header, the start of a data: URL, or Blob.type for a blob: URL)

  2. With a value: In that case the value is used as a filename. \ and / are converted to underscores to prevent the generation of illegal filenames.

Your case is use case (2) so you can do:

@foreach ($files as $file)
   <a href="{{ asset('storage/'. $file->file) }}" download="{{$file->file_original_name}}">{{ $file->file_name }}</a>
@endforeach

Do read the documentation for any caveats (e.g. this doesn't work cross-origin).

Upvotes: 1

Related Questions