Laravel 5.5 get file after uploading with Storage - php

In my Laravel 5.5 project I am having a problem in showing uploaded files. I uploaded the files using Storage. The part of store action of the controller is indicated below.
if ($request->hasFile('content_uz'))
{
$path = $request->file('content_uz')->store('/content/lesson'.$topic->lesson->id.'/topic'.$topic->id);
$data->content_uz = $path;
}
if ($request->hasFile('content_ru'))
{
$path = $request->file('content_ru')->store('/content/lesson'.$topic->lesson->id.'/topic'.$topic->id);
$data->content_ru = $path;
}
Uploading happened successfully. The path to uploaded 'content_uz' file is stored with "storage/app/content/lesson2/topic3" path and content_uz column is stored in my db as below:
content\lesson2\topic3\WSjrlG9a1ermGDOvRJTjn9iEIhfFvhVzjaOs6l79.mp4
How can I display the files in my Blade template? I searched the web, but with no result.

You can use method like this,
public function showFile() {
header("Content-type: video/mp4");
return Storage::get($filePath);
}
I hope this will help.

You may access the files of storage directory by two ways.
If your files are publicly accessible then you may follow laravel public disk.
If your files are protected or private then you may declare a route to access the files.
Route::get('content/{lesson}/{topic}/{file}', function($lesson, $topic, $file)
{
//Check access logic
$filePath = '/content/' . $lesson . '/' . $topic . '/' . $file;
return Storage::get($filePath);
});

Related

Laravel 8 returns two different folders for the same path

I'm using Laravel 8.35.1 and try to check if a folder exists or - if not - create it.
The paths are:
data/4d61c171-cd94-48ec-82bb-8fee7394471a/processor/333afcbc-37be-4e19-bddc-605c21e766bb
data/4d61c171-cd94-48ec-82bb-8fee7394471a/downloads/333afcbc-37be-4e19-bddc-605c21e766bb
The folders should be created in storage/app/.
I do the same for both paths:
$processFolder = $fileHelper->existOrCreate('data/4d61c171-cd94-48ec-82bb-8fee7394471a/processor/333afcbc-37be-4e19-bddc-605c21e766bb');
$downloadFolder = $fileHelper->existOrCreate('data/4d61c171-cd94-48ec-82bb-8fee7394471a/downloads/333afcbc-37be-4e19-bddc-605c21e766bb');
public function existOrCreate($path)
{
if (!File::exists($path)) {
if (!File::makeDirectory($path, 0755, true)) {
send_error_mail('Folder could not be created: ' . $path);
}
}
return $path;
}
The problem is, that always the downloads folder is wrongly created in
/public/data/4d61c171-cd94-48ec-82bb-8fee7394471a/downloads/333afcbc-37be-4e19-bddc-605c21e766bb
and the processor folder is correctly created in
/storage/app/data/4d61c171-cd94-48ec-82bb-8fee7394471a/processor/333afcbc-37be-4e19-bddc-605c21e766bb
Any ideas?
Use the Storage facade instead of the File facade.

laravel - saving and accessing an uploaded file

I am studying some laravel code that I downloaded and I am getting some problem.
This supposed to be the functions to save,delete and download the files but the problem is.
The files are being saved in a folder named with a number on "storage\app\public\project-files\" (i.e. storage\app\public\project-files\11), both destroy and download methods are referencing different paths, I tried to change but didn't worked, download show FileNotFoundException and destroy just remove from the database but not from the folder
So is this code wrong? How It supposed to be?
I've read about using artisan:link but seems odd to me run this command every time I want upload a file to make a link
PS. I cheched the routes, so the methods are being called
Thanks
public function store(Request $request)
{
if ($request->hasFile('file')) {
$file = new ProjectFile();
$file->user_id = $this->user->id;
$file->project_id = $request->project_id;
$request->file->store('public/project-files/'.$request->project_id);
$file->filename = $request->file->getClientOriginalName();
$file->hashname = $request->file->hashName();
$file->size = $request->file->getSize();
$file->save();
$this->project = Project::find($request->project_id);
return view('project-files');
}
public function destroy($id)
{
$file = ProjectFile::find($id);
File::delete('storage/project-files/'.$file->project_id.'/'.$file->hashname);
ProjectFile::destroy($id);
$this->project = Project::find($file->project_id);
return view('project-files');
}
public function download($id) {
$file = ProjectFile::find($id);
return response()->download('storage/project-files/'.$file->project_id.'/'.$file->hashname);
}
You are storing files in storage so i assume you have uploaded image in the following path
project\storage\app\public\project-files
if this is the path then you can delete using
Storage::delete('public/project-files/1.JPG');
for Downlaoding file
$path= storage_path('app/public/project-files/3.JPG');
return response()->download($path);

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;
}

Codeigniter deleting files in a directory not working

I am trying to delete pdf files from a folder. I have written the delete_files function as follows
public function delete_files($company_id)
{
$this->load->model('search_model');
$company = $this->search_model->get_company($company_id);
$username = $company[0]['username'];
$path=$this->config->base_url('/uploads/'.$username . '/' . 'uploaded');
$this->load->helper("file"); // load the helper
delete_files($path, true); // delete all files/folders
}
when i did echo $path; it shows the right path where i want the files deleted but when i run the entire function nothing happens and i just get a white screen.
You need to use path to file and not resource locator.
$path = FCPATH . "uploads/$username/uploaded";
try this code
Use
$path = FCPATH . "uploads/$username/uploaded";
unset($path);

Laravel: load images stored outside 'public' folder

I'm trying to display an image stored outside the 'public' folder in my view. These are simple profile images whose paths are stored in the DB. The path looks like
/Users/myuser/Documents/Sites/myapp/app/storage/tenants/user2/images/52d645738fb9d-128-Profile (Color) copy.jpg
Since the image is stored a DB column for each user, my first thought was to create an Accessor in the User model to return the image. I tried:
public function getProfileImage()
{
if(!empty($this->profile_image))
{
return readfile($this->profile_image);
}
return null;
}
That produced unreadable characters in the view. I also tried file_get_contents() in place of read file. Any suggestions about how this might be accomplished?
How about this (just tested it myself and it works):
The view:
<img src="/images/theImage.png">
Routes.php:
Route::get('images/{image}', function($image = null)
{
$path = storage_path().'/imageFolder/' . $image;
if (file_exists($path)) {
return Response::download($path);
}
});
Here is a slightly modified version of #Mattias answer. Assume the file is in the storage/app/avatars folder which is outside the web root.
<img src="/avatars/3">
Route::get('/avatars/{userId}', function($image = null)
{
$path = storage_path().'/app/avatars/' . $image.'.jpg';
if (file_exists($path)) {
return response()->file($path);
}
});
Probably needs and else. Also I have wrapped mine inside the middleware auth Route Group which means you have to be logged in to see (my requirements) but I could do with more control over when it is made visible, perhaps alter the middleware.
EDIT
Forgot to mention that this is for Laravel 5.3.
Here's what I came up with:
I'm trying to show the images in the view, not download. Here's what I came up with:
Note that these images are stored above the public folder, which is why we have to take extra steps to display the image in the view.
The view
{{ HTML::image($user->getProfileImage(), '', array('height' => '50px')) }}
The model
/**
* Get profile image
*
*
*
* #return string
*/
public function getProfileImage()
{
if(!empty($this->profile_image) && File::exists($this->profile_image))
{
$subdomain = subdomain();
// Get the filename from the full path
$filename = basename($this->profile_image);
return 'images/image.php?id='.$subdomain.'&imageid='.$filename;
}
return 'images/missing.png';
}
public/images/image.php
<?php
$tenantId = $_GET["id"];
$imageId = $_GET["imageid"];
$path = __DIR__.'/../../app/storage/tenants/' . $tenantId . '/images/profile/' . $imageId;
// Prepare content headers
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$length = filesize($path);
header ("content-type: $mime");
header ("content-length: $length");
// #TODO: Cache images generated from this php file
readfile($path);
exit;
?>
If somebody has a better way, please enlighten us!! I'm very interested.

Categories