How to display image from aws s3 in blade laravel 5.2 - php

I have created a method for getting the data(image file) from aws S3 like this :
public static function getImage ($imagePath)
{
if(Storage::exists($imagePath))
{
return Storage::disk('s3')->get($imagePath);
}else
{
return 'No Image';
}
}
I'm sure that those image is exist on the aws, so there is no problem with that.
And then I use above method as the src in my blade view like this :
{!!Html::image(getImage($myPath),'logo',['width'=>60,'height'=>55])!!}
$myPath here already point to the specific file on aws for example : bucket/file.jgp. But when I run my webpage, this Html::Image gives a view like this :
What's going on here ? Why Html::image can't render my image file ? :(

Works on Laravel 6.x
<img src="{{Storage::disk('s3')->url($imagePath)}}">

You can use Storage::url($imagePath). Please see Filesystem / Cloud storage on laravel docs

{!!Html::image(<Your S3 bucket URL>.$myPath),'logo',['width'=>60,'height'=>55])!!}
You can save the S3 URL in a config file and use the config value instead of writing actual value everytime.

I had the same issue. This code snippet solved it
<img src="{!! url(<path to your image>) !!}" />

First, you need to give it public promotion in the controller
$path = Storage::disk('s3')->put('profileImages/', $request->file('profile_image'), 'public');
//save image name in database
$user->profile_image = basename($path);
In blade file
<img src="{{Storage::disk('s3')->url('profileImages/' . $user->profile_image)}}" />

You can add an accessor like follow to get Image URL
It returns URL to the image and you can access it by $profile->image
public function getImageAttribute($value)
{
if ($value) {
return Storage::disk('s3')->url($value);
}
return "https://source.unsplash.com/96x96/daily";
}
I assume you save image as follow
$path = $request->file('image')->store('images', 's3');
Storage::disk('s3')->setVisibility($path, 'public');
$profile->update([
'image' => $path
]);
You can check this commit for more detail
https://github.com/itxshakil/ediary/commit/23cb4b1cb7b8a4eac68f534e8c5b6897abc6421a

I have read every solution and no one has pointed it directly. So I thought to write my answers. For this problem I just required to add this simple line and boom, it starts working. But I got access denied alert you should check that problem too.
<img class="img-responsive" src="{!! Storage::disk('s3')->url('thumbs/' . $business->image->path) !!}" alt="thumb">

This works
Storage::disk('s3')->url($imagePath)
and also from your Minio Browser.
You have to Add a policy to Read and Write

I think that private visibility of images is an important security feature.
I found a solution :-)
Method in Controller:
/**
* #param string $name : image name on bucket
* ( stored if you want into database )
*/
public function show( $name ) {
$path = config('filesystems.disks.s3.base_directory') . '/' . $name;
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = Storage::get( $path );
$base64 = 'data:image/' . $type . ';base64,' . base64_encode( $data );
return view( 'show', [ 'src' => $base64 ]);
}
The view:
...
<div class="panel panel-primary">
<div class="panel-heading"><h2>Laravel File Retrive with Amazon S3 </h2></div>
<div class="panel-body">
**<img src="{{ $src }}"/>**
</div>
</div>
...

Related

How to return json response and Storage data together in Laravel?

I'm trying to return query data and storage Images from laravel controller. My code looks like following :
class ClaimController extends Controller{
.....
public function show(Claim $claim)
{
$front_image = Storage::disk('do_spaces')->get($claim->images->front_image); //image file
$back_image = Storage::disk('do_spaces')->get($claim->images->back_image); //image
// return $front_image [works]
$claim = Claim::all();
//this throws error
return response()->json([
'claim' => $claim,
'images' => [$front_image, $back_image]
]);
}
}
Now I far I understand return->response()->json([]) doesn't send image file. How I can return all data together to frontend app ?
you have the option to return the images from original server which they are stored in or you can return an encoded version of the image as string and in front end reconstruct it.
$path = 'myfolder/myimage.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
And then use it in front like this :
var image = new Image();
image.src = 'data:image/png;base64,iVBORw0K...';
document.body.appendChild(image);
This is the link for second part.
You can use Storage::url()
$st=\Illuminate\Support\Facades\Storage::disk('do_spaces')->url($claim->images->front_image);
dd(url($st));
Storage::url() return image path and then url() will return full url path
"http://127.0.0.1:8000/storage/imagefolder/filename"
Make sure to symbolic link to storage folder by running following command
php artisan storage:link
Also you can do the following without storage url
asset('storage/'.$claim->images->front_image)

Symfony 4 file controller helper how to convert binary file to HTML compatible?

Trying to retrieve an image from outside public. I have been using file controller helper but still can't get it to work:
here is my code that is returned as AJAX to update the IMG SRC path
$imgPATH = $this->getParameter('kernel.project_dir').'/uploads/user_profile_pictures/';
$ext = [".png", ".jpg", ".jpeg", ".gif"];
foreach ($ext as $x) {
$imgPath = $this->getParameter('kernel.project_dir').'/uploads/user_profile_pictures/'.$usertoPic.$x;
if (file_exists($imgPath)) {
return $this->file($imgPath , 'userProfilePicture.png' , ResponseHeaderBag::DISPOSITION_INLINE);
}
}
The image is found by PHP but I get the following broken HTML in the browser; I think this is because it is binary ? how can I convert it to HTML compliant ?
<img id="userIMG" src="�PNG��IHDR���S���S���lЬW���pHYs��.#��.#x�v��OiCCPPhotoshop ICC profile��xڝSgTS�=���BK���KoR RB���&*!J�!��Q�EEȠ�����Q,������������{�kּ������>�����H3Q5��B�������.#�$p��d!s�#��~<<+"���x���M��0���B�\���t�8K��#z�B��#F���&S���`�cb��P-�`" �������{�[�!���="" e�d�h;���v�e�x0�fk�9��-�0iwfh��������="" �0q��)�{�`�##x����f�w<�+��*��x��<�$9e�[-qww.(�i+6aa�#.�y�2�4�����������x����6��_-��"bb���ϫp#���t~��,="" ��;�m��%�h^�u��f�#�����w�p�~<<e���������j�b[a�w}�g�_�w�l�~<�����$�2]�g�����l�ϒ="" �b��g�����"�ib�x*�qq�d���2�"�b�)�%��d��,�="">
Your browser cannot have access to a file that is not in the public (for Symfony 4) folder. That is pretty much the whole point of having a "public" directory.
What you can do is serving the file directly as a binary response given a certain link in your app, like documented here:
https://symfony.com/blog/new-in-symfony-3-2-file-controller-helper
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class ImgController extends Controller
{
/**
* #Route("/get-my-img")
*/
public function getImg()
{
$basePath = $this->getParameter('kernel.root_dir').'/uploads/user_profile_pictures/';
return $this->file($basePath . "img.png");
}
}
// this should work quite simple:
// site/public/css/style.css
<link href="{{ asset('css/style.css') }}" rel="stylesheet" />
// site/upload/favicon.ico
<img src="{{ asset('../upload/favicon.ico') }}" />
$target_dir = '/upload/favicon.ico'; // param in config
$file = $this->getParameter('kernel.project_dir') . $target_dir;
if(is_file($file)) dump('found: ' . $file);

The blade only load the default picture?

I have seen this answer [
[Determining If a File Exists in Laravel 5 and tried to implement the same method in my project.
I'm using Imageintervention and Laravel 5.4. I have a PropertyController with the following validation code:
//? file upload
if ($request->hasFile('image')) {
$image = $request->file('image');
$filename = time() .'.' .$image->getClientOriginalExtension();
$location = public_path('/imgs/properties/' . $filename);
Image::make($image)->resize(400, 300)->save($location);
$property->image = $filename;
}
//store in the DB
In my show blade i have the following syntax:
<div class="thumbnail">
#if(file_exists(public_path().'../imgs/properties/. $filename'))
<img src="../imgs/properties/{{ $property->image }})" alt="">
#else
<img src="../dist/img/villa.jpg" alt="">
#endif
I put the following code in my Property Model:
public function image()
{
if(file_exists( public_path() . '/imgs/properties/' . $filename)) {
return '/imgs/properties/' . $filename;
} else {
return '../dist/img/villa.jpg';
}
If I register a property with an image I only get the default image and not the newly registered image. I have checked in my properties folder and the image newly registered image is there waiting i fix the problem. Do you have any idea about what went wrong?
Thank you in advance!

Laravel 5.3 storage cant find uploaded file

I am using laravel Filesystem to store images, the image will be uploaded inside the default storage, example:
/home/user/Projects/mywebapp/storage/app/images/posts/1/e392e17926559e7cc4e7934f.png
I didnt change the config/filesystem.php and here is my controller method to upload an image,
public function storeImage( Request $request ) {
$image = $request->file( 'image' )->store( 'images/posts/'.Auth::user()->id );
echo Storage::url( $image ); // <- print the url of the uploaded image
}
This would print the image url like this,
http://localhost:8000/storage/images/posts/1/e392e17c6a8d7926559e8e7cc4e7934f.png
But the image file is not accessable from the browser!
I dont want to use php to dynamically fetch the images, i just wanted to make them publicly accessable over http. How to display the image?
you just have to make a change in config\filesystems.php form
'default' => local,
to 'default' => public,
then in console run php artisan storage:link
then try the above code and it will work
For me it worked when I added "../" to the url of the file:
#foreach($arquivos as $i)
<li class="list-group-item"> <img src="{{ asset('img/pdf.png') }}" /> {{ $i -> nome }} </li>
#endforeach
And I am saving the file like this:
$ext = $request->arquivo->extension();
$path = $request->arquivo->storeAs('/relatorios', $nameoffile. "." . $ext);

Laravel Access Images outside public folder

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= ..."
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.
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
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)}}">
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;
}

Categories