0
votes

Im currently storing images via file input like so:

<input type="file" name="images" class="form-control">

Inside the store function, i store the file & the url like so:

      $blog = new Blog;

      $path = Storage::putFile('image', $request->file('images'));

      $url = Storage::url($path);

      $blog->file = $url;
      $blog->save();

Whichs works just fine. As a path in tinker i get for the file string for each blog ($blog->file) the following response:

"/storage/images/GmjAKA6FkId7vli2aw1oq2Z3MkAzZQRxGPoQeVud.jpeg"

To display an image on the view part, i use:

<img src="asset/{{ $blog->file}}" alt="" class="card-img-top">

which prints out:

<img src="asset/storage/images/GmjAKA6FkId7vli2aw1oq2Z3MkAzZQRxGPoQeVud.jpeg" alt="" class="card-img-top">

in the console.

Inside storage/images i can also see all images that been uploaded. However, in my text editor there is an "app" folder in between storage and images like so:

"storage/app/images"

which is the reason no image gets displayed.

Since i'm using Storage.put, why is Storage saving the path as "storage/images/" instead of "storage/app/images"?

Filesystems.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Filesystem Disk
    |--------------------------------------------------------------------------
    |
    | Here you may specify the default filesystem disk that should be used
    | by the framework. The "local" disk, as well as a variety of cloud
    | based disks are available to your application. Just store away!
    |
    */

    'default' => env('FILESYSTEM_DRIVER', 'local'),

    /*
    |--------------------------------------------------------------------------
    | Default Cloud Filesystem Disk
    |--------------------------------------------------------------------------
    |
    | Many applications store files both locally and in the cloud. For this
    | reason, you may specify a default "cloud" driver here. This driver
    | will be bound as the Cloud disk implementation in the container.
    |
    */

    'cloud' => env('FILESYSTEM_CLOUD', 's3'),

    /*
    |--------------------------------------------------------------------------
    | Filesystem Disks
    |--------------------------------------------------------------------------
    |
    | Here you may configure as many filesystem "disks" as you wish, and you
    | may even configure multiple disks of the same driver. Defaults have
    | been setup for each driver as an example of the required options.
    |
    | Supported Drivers: "local", "ftp", "sftp", "s3", "rackspace"
    |
    */

    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
        ],

        's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
        ],

    ],

];

i ran php artisan link:storage before (stated in the documentation).

If anyone has an idea what causes this, i'll be glad to hear it!

Thanks in advance everyone!

4

4 Answers

1
votes

If anyone is looking for a solution to this, here is a good tip: use laravel-medialibrary.

Medialibrary is a Laravel (5.6 and up) package that can associate all sorts of files with Eloquent models. It provides a simple, fluent API to work with.

Using the example above, you could simply do something like the following:

$blog = Blog::find(1);
$blog->addMedia($pathToFile)->toMediaCollection('images');

Or, if you want to directly handle your uploads, like the case in the problem:

$blog->addMediaFromRequest('image')->toMediaCollection('images');

To retrieve files you can use the getMedia-method. The method returns a collection of Media-objects, in other words, it return all media for the given Model:

$mediaItems = $blog->getMedia();

You can retrieve the url and path to the file associated with the Media-object using getUrl and getPath:

$publicUrl = $mediaItems[0]->getUrl();
$publicFullUrl = $mediaItems[0]->getFullUrl(); //url including domain
$fullPathOnDisk = $mediaItems[0]->getPath();

In resume, by using this library you don't need to worry about any storage configuration directly, you can do everything by calling methods on the model itself. I strongly suggest you to take a look at the Docs, it's really easy to use.

0
votes

It's not php artisan link:storage but php artisan storage:link.

You have to you use the asset() helper to get the right path to your image in storage :

<img src="{{ asset($blog->file) }}" alt="" class="card-img-top">

0
votes

It's not a good practice to expose your Storage Directory,

//save with

Storage::disk('local')->put('/dir_name/'.unique_file_name.extension, File::get(tmp_dir_received));

it globally references your storage/app directory

to retrieve file content from storage/app/dir_name.

<img src="{{ url('/dir_name/'.$blog->file) }}" alt="" class="card-img-top">
0
votes

Thanks everyone for responding!

I've came up with the following 'solution':

I just store in the public folder, via:

  $path = Storage::putFile('public', $request->file('images'));

It seems that storage:link can only expose the public folder.