2
votes

I need to store images in a backend for logged in users. The stored images need to be protected and not visible from the outside (public). I choosed a "storage" folder for this.

I came up with this in my Controller:

public function update(Request $request, $id)
{

  //Show the image
  echo '<img src="'.$_POST['img_val'].'" />';

  //Get the base-64 string from data
  $filteredData=substr($_POST['img_val'], strpos($_POST['img_val'], ",")+1);

  //Decode the string
  $unencodedData=base64_decode($filteredData);

  //Save the image
  $storagepath = storage_path('app/images/users/' . Auth::user()->id);
  $imgoutput = file_put_contents($storagepath.'/flyer.png', $unencodedData);

  return view('backend.flyers.index')->withImgoutput($imgoutput)
                                     //->withStoragepath($storagepath);

}

after hitting the save button, which triggers the update() I am able to see the image in my view, and it is also stored in my folder (current users=10) "storage/app/images/users/10/flyer.png"

my question is how can I access the image path? I want to show the stored image with img src="">. I have no idea what to put inside "src= ..."

4
Are you sure you went through any basic PHP/Laravel readings?Mina Abadir
This isn't helpfulMamulasa
Actually, you are using functions that does not exist in Laravel. Your code is showing lack of information. I would really recommend going through some PHP and Laravel readings before going through a new application.Mina Abadir
For instance, you do not echo strings from Controller, then return a view. It does not work this way.Mina Abadir

4 Answers

4
votes

While dealing with user file uploads in web applications, the major aspect is about user's content's security. One should use secure way to upload private files of a user in web applications.

As in your case, you want to access user's image outside public folder. This can be done in a most secure way as given below.

First of all create a directory right in the root directory of Laravel (where the public folder is located), let the directory's name be uploads. Use this directory to upload private user files.

In the case of images create an another directory inside uploads as uploads/images/ inside uploads directory so that you can have a different storage locations for different type of files.

Remember to upload the image in images directory with a different name and without their extensions so that it looks like a extension-less file. Keep the file name and its extension in the database which can be used later to retain image's location.

Now you need to create a separate route to show user's image.

Route::get('users/{id}/profile_photo', 'PhotosController@showProfilePhoto')->name('users.showProfilePhoto');

PhotosController.php

class PhotosController extends Controller {

    private $image_cache_expires = "Sat, 01 Jan 2050 00:00:00 GMT";
    public function showProfilePhoto($id) {
      $user = User::find($id);
      $path = base_path() . '/uploads/images/';

      if($user && $user->photo) // Column where user's photo name is stored in DB
      {
        $photo_path = $path . $user->photo; // eg: "file_name"
        $photo_mime_type = $user->photo_mime_type; // eg: "image/jpeg"
        $response = response()->make(File::get($photo_path));
        $response->header("Content-Type", $photo_mime_type);
        $response->header("Expires", $this->image_cache_expires);
        return $response;
      }
      abort("404");
    }

}

The method above inside PhotosController - showProfilePhoto($user_id) will run as soon as you access the route named - users.showProfilePhoto.

Your HTML code will look like this.

<img src="<?php echo route('users.showProfilePhoto', array('id' => $user->id)); ?>" alt="Alter Text Here">

The above code will work like a charm and the image will be shown to the user without declaring/publishing the proper image path to public. According to me this is the secure way to deal with file uploads in web applications.

0
votes

You can do this like this:

 Route::get('images/{filename}', function ($filename)
 {
     $path = storage_path() . '/' . $filename;

     if(!File::exists($path)) abort(404);

     $file = File::get($path);
     $type = File::mimeType($path);

     $response = Response::make($file, 200);
     $response->header("Content-Type", $type);

     return $response;
 });

Reference:

Laravel 5 - How to access image uploaded in storage within View?

Or Alternatively you can use this library: https://github.com/thephpleague/glide

Just use composer to install it in your project

By default, this will render images from your storage, and allow you to do all sorts of things with it such as cropping, color correction etc.

Reference:

http://glide.thephpleague.com/

https://laracasts.com/discuss/channels/laravel/laravel-5-how-can-we-access-image-from-storage?page=1

0
votes

Atimes you might have some images you do not wish to store in public directory for some various reasons.

Although storing your images has lots of advantages.

There are many ways you can achieve this, however I have this simple solution.

You should create a helper class like so if already don't have one

<?php namespace App\Services;

class Helper
{
    public function imageToBase64($path)
    {
        $type = pathinfo($path, PATHINFO_EXTENSION);
        $data = file_get_contents($path);
        return 'data:image/' . $type . ';base64,' . base64_encode($data);
    }
} 

Then in your view (blade)

@inject('helper', 'App\Services\Helper')

 <img width="200" height="250" src="{{$helper->imageToBase64(storage_path('app/images/users/' . Auth::user()->id)}}">
0
votes

It will work 100% work. Open file filesystem in app/config/filesystem.php and write like that

'profile' => [
            'driver' => 'profile',
            'root'   => '/home/folder/public_html/projectname/public/profiles',
        ],

Add this file at top

use Illuminate\Support\Facades\Storage;

My variable name is

 $directoryName = 'profile'; 
 $imageName = $request->image;  // image is array of base64 encoded urls
 $directory_path ='profiles';

Below function save your file in public/profiles folder.

    function UploadImagesByBase64($directoryName, $imageName,$directory_path)
    {
            $data = array();
            $image = $imageName;
            foreach ($image as $image_64) {               
                if($image_64 !=null){
                    $extension = explode('/', explode(':', substr($image_64, 0, strpos($image_64, ';')))[1])[1];   // .jpg .png .pdf
                    $replace = substr($image_64, 0, strpos($image_64, ',')+1); 
                  // find substring fro replace here eg: data:image/png;base64,
                   $image = str_replace($replace, '', $image_64); 
                   $image = str_replace(' ', '+', $image); 
                   $imageName = Str::random(10).time().'.'.$extension;
                   Storage::disk($directoryName)->put($imageName, base64_decode($image));
                   $data[] = $directory_path.'/'.$imageName;
                    }
            }
            $imageName = implode(',', $data);
            return $imageName;
}