when I try to visualise my picture with this basic url on google :
domain.com/storage/transports/picture.png
I get (404) not found.
(I don't have this error for a file outside the storage symlink in my tree picture and I can totaly see it without any problems, exemple :
domain.com/logo.svg
I have used php artisan storage:link to create the symlink, so far I'm abble to store the pictures exactly where I want to with that controller :
public function storeTransports(Request $request)
{
try{
session(['content'=>'content_transports']);
$request->validate([
'name' => [ 'string', 'max:255'],
'picture' => [ 'required','image','mimes:jpeg,png,jpg,gif,svg', 'max:2048']
]);
if(Transport::where('name', $request->name)->first()){
return redirect(RouteServiceProvider::HOME)->with('error_transports', 'Transport already exists');
}
else{
if($request->hasFile('picture')){
$sanitized_image_name = strtolower(preg_replace("([^A-Za-z0-9])", "", $request->name)).'_'.time();
$image_name = $sanitized_image_name.'.'.$request->picture->extension();
Transport::create([
'name' => $request->name,
'path_picture' => $image_name
]);
$request->picture->storeAs('public/transports',$image_name);
}
}
return redirect(RouteServiceProvider::HOME)->with('success_transports', 'Transport saved successfully');
} catch (\Illuminate\Database\QueryException $e){
return redirect(RouteServiceProvider::HOME)->with('error_transports',$e->errorInfo);
}
}
I can also visualize my pictures in my public folder :
i've rm rf public/storage many times already
here is my configfiles.php :
<?php
return [
'default' => env('FILESYSTEM_DISK', 'public'),
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'throw' => false,
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],
'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'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
],
'links' => [
public_path('storage') => storage_path('app/public'),
],
];
I appreciate your help, I've been looking at all the stackoverflow talking about that for the past hour.
PS: I don't use vagrant.
EDIT:
i finally fixed my issue, as Matty10209 mentoned here,
"[...]When running "php artisan storage:link", Laravel creates an absolute path for the image to your local directory. Docker does not like this and wants a relative one, so it breaks the image link and you get a 404. You have to create the symlink manually[...]"
"[...] Go to docker and the CLI of your project container (should be at the bottom). Delete the current symlink you have created with Laravel, then navigate to the path you wish to create a new one. and run
ln -s ../storage/app/public storage
[...]"
Related
I still a newbie in Laravel. Please help me to solve my issue. I stuck on to prevent the file from the public. I trying to make the file access from public to private in Laravel 7.
I put all of the links in the auth it made all of the links required access before using it. I was tried to access some links to create a record. I can't do it and the system required the auth but when I use the URL http://127.0.0.1:8000/storage/actions/filename.something without log-in to access the image file. I still can see the file.
This is my route
Route::group(['prefix' => 'admin', 'middleware'=> ['auth', 'administrator']], function () {
//Action
Route::get('/addAction', 'admin\ActionController#create');
Route::get('/deleteAction/{id}', 'admin\ActionController#delete');
Route::get('editAction/{id}', 'admin\ActionController#edit');
Route::post('/addAction', 'admin\ActionController#store');
Route::post('/updateAction/{id}', 'admin\ActionController#update');
Route::get('/allAction', 'admin\ActionController#index');
Route::get('/delete/actionImage/{id}', 'admin\ActionController#deleteimages');
});
This is the controller that I use to store the data to the database and the image to the file path.
public function index(){
return view('admin.allAction')
->with('actions',Action::all())
->with('challenges',Challenge::all())
->with('users',User::all())
->with('status',Status::all())
->with('images',Images::all());
}
public function create(){
$users = DB::table('users')
->where('role','2')
->get();
return view('admin.addAction')
->with('users', $users)
->with('status',Status::all());
public function store(Request $request){
$request->validate([
'name' => 'required|string|max:188',
'objective' => 'string|max:888',
'images' => 'required',
'images.*' => 'file|image|mimes:jpeg,png,jpg|max:8000',
]);
// Insert Data to Table
$action=new Action();
$action->name=$request->name;
$action->objective=$request->objective;
$action->status_id=$request->status_id;
$action->owner_id=$request->owner_id;
$action->challenge_id=$request->challenge_id;
/*dd($action);*/
$action->save();
if ($request->hasfile('images')) {
$images = $request->file('images');
foreach($images as $image) {
$name = time().'-'.$image->getClientOriginalName();
$name = str_replace(' ','-',$name);
/*$path =*/ $image->storeAs('actions', $name, 'public');
Images::insert([ /*OrUpdate*/
'name' => $name,
'action_id' => $action->id,
]);
}
}
Session()->flash("success", "Success!");
return redirect('/admin/addAction');
My filesystem.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
],
],
'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 never do private file before I don't know how to do it. I tried to search how to on the internet but I still can't make it possible.
Thank you for all of the comments in advance and sorry for my English.
I'm messed with the paths to get UniSharp / laravel-filemanager working on the server. In local mode it works perfectly but now I'm making the change of routes for production in online mode and I am not clear at all.
The problem is that it loads the images but they are not displayed either on the page or in the filemanager itself. In filemanager, I can see a red square with a cross (as error).
Let's see if anyone knows how to write the correct routes. I have tried many things but I'm messed.
The server files scaffolding:
server_files
my_laravel_app
public_html
another_files
The config filesystem.php file in Laravel:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('public_html'),
'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'),
'endpoint' => env('AWS_ENDPOINT'),
],
],
'links' => [
public_path('storage') => storage_path('app/public'),
],
I have, default uploading path in filemanager's lfm.php:
'disk' => 'public',
In case it helps something, this is my index.php ubicated at public_html:
if (file_exists(__DIR__.'/../my_app_laravel/storage/framework/maintenance.php')) {
require __DIR__.'/../my_app_laravel/storage/framework/maintenance.php';
}
require __DIR__.'/../my_app_laravel/vendor/autoload.php';
$app = require_once __DIR__.'/../my_app_laravel/bootstrap/app.php';
And this is ServiceProviders.php
public function register()
{
$this->app->bind('path.public', function() {
return base_path().'/public_html';
});
}
How should be the correct path in filesystem to allow filemanager can access to images and display them?
Note: the public_html folder has the symbolic link as you can see at filesystem.php.
I have checking routes and I solved temporary:
I changed:
'public' => [
'driver' => 'local',
/* this */ 'root' => storage_path('app/public'),
/* this */ 'url' => env('APP_URL').'/storage/app/public',
'visibility' => 'public',
],
And now I can upload and see the images in file manager and inside the web app. But now the problem is that users can visit the image url and see the private route of the folder:
http//mi_lar_app/storage/app/public/photos/31/art_1/fig_1.0.png
Some help????
If you have similar problems, the procedure I do in this case was to create a symbolic link with routes (I created a php file because I haven't access to SSH on my server):
<?php
/*__DIR__ is the directory file, where you save this file.php */
$mytargetDIR = __DIR__.'/../mi_lar_app/storage';
$mylinkDIR = __DIR__.'/storage';
symlink($mytargetDIR,$mylinkDIR);
echo 'Todo ok/ Symlink process successfully completed';
?>
And important, remember clean cache and routes every changes. If you don't have SSH access:
<?php
Artisan::call('cache:clear');
Artisan::call('config:cache');
Artisan::call('route:cache');
Artisan::call('view:clear');
return 'Todo limpio/All is cleaned';
?>
And next this little explanation, some help to me?? :)
On Laravel 8
file_get_contents(asset('storage/list.json');
Give me:
ErrorException
file_get_contents(http://localhost:8000/storage/list.json): failed to
open stream: HTTP request failed!
But: http://localhost:8000/storage/list.json exist and it is accesible via browser for example.
On my config/filesystem.php iv'e:
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
],
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
And ive created the symbolic link with:
php artisan storage:link
command.
I've tried even to add manually file perssion to storage folder as described in the filesystem.php but nothing change.
You should use absolute paths when you want to work with files. file_get_contents() is fine. There are some file wrappers available in laravel but internally they all use file_get_contents().
Try
file_get_contents(public_path(asset('storage/list.json')));
If getting from storage file try
file_get_contents(storage_path('app/assets/list.json'));
See https://laravel.com/docs/5.5/helpers#method-resource-path
I'm using image field in laravel backpack 4.0 and it uploads the images without any problems. When I delete the image by using the delete button, it deletes the register (E.N. Probably means "it deletes the image from the database"), but not the image file from my local folder. I've checked the answer from backpack for laravel deleting image , but it did not help to fix my issue.
My config/filesystem:
'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'),
],
],
My Model code:
public function setImageAttribute($value)
{
$attribute_name = "image";
$disk = config('backpack.base.root_disk_name'); // or use your own disk, defined in config/filesystems.php
$destination_path = env('FOLDER_PUBLIC')."/uploads/medias"; // path relative to the disk above
// if the image was erased
if ($value==null) {
// delete the image from disk
\Storage::disk($disk)->delete($this->{$attribute_name});
// set null in the database column
$this->attributes[$attribute_name] = null;
}
// if a base64 was sent, store it in the db
if (starts_with($value, 'data:image'))
{
// 0. Make the image
$image = \Image::make($value)->encode('jpg', 90);
// 1. Generate a filename.
$filename = rand ( 10000 , 99999 ).'-'.strtolower(trim(preg_replace('/[\s-]+/', '-', preg_replace('/[^A-Za-z0-9-]+/', '-', preg_replace('/[&]/', 'and', preg_replace('/[\']/', '', iconv('UTF-8', 'ASCII//TRANSLIT', $this->title))))), '-')).'.jpg';
// 2. Store the image on disk.
\Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
// 3. Save the public path to the database
// but first, remove "public/" from the path, since we're pointing to it from the root folder
// that way, what gets saved in the database is the user-accesible URL
$public_destination_path = Str::replaceFirst(env('FOLDER_PUBLIC').'/', '', $destination_path);
$this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
}
}
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
\Storage::disk('public')->delete($obj->image);
});
}
I have tried to change:
\Storage::disk('public')->delete($obj->image);
With:
\Storage::disk(config('backpack.base.root_disk_name'))->delete($obj->image);
But it is not working either,
Can anyone help me?
Sorry for my english
You're on the right track. Looks like something is misconfigured if code in boot() doesn't affect any changes. My guess is that that the $obj->image path to the file you're trying to delete is NOT the exact path to the file. You might need to add the destination folder there too.
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
$disk = config('backpack.base.root_disk_name');
$destination_path = env('FOLDER_PUBLIC')."/uploads/medias";
\Storage::disk($disk)->delete($destination_path.'/'.$this->image);
});
}
If this works, to further improve the code, I recommend you turn the $disk and $destination_path variables into properties on the PHP class itself (the Laravel model). That way, you only define them in one place, and you can then use them in both methods, with something like $this->imageDisk and $this->imagePath.
Thanks for your reply, At the end I have fixed it, making this change:
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
\Storage::disk('uploads')->delete($obj->image);
});
}
And in config/filesystem:
'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'),
],
'uploads' => [
'driver' => 'local',
/* 'root' => base_path().'/web/storage',*/
'root' => base_path().'/'.env('FOLDER_PUBLIC'),
],
],
Regards
I'm trying to store a file in the public folder storage/app/public/ but for some reason Laravel just seems to put it in the private storage/app/ folder.
If I understand correctly I'm supposed to just set the visibility to 'public' but that doesn't seem to change anything:
Storage::put($fileName, file_get_contents($file), 'public');
When I call getVisibility I get public so that seems to work fine:
Storage::getVisibility($fileName); // public
These are the settings in my filesystems.php:
'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_KEY'),
'secret' => env('AWS_SECRET'),
'region' => env('AWS_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
When you call Storage::put, Laravel will use the default disk which is 'local'.
The local disk stores files at its root: storage_path('app'). The visibility has nothing with where the file should be stored.
You need to choose the public disk which will store the files at its root: storage_path('app/public'),
To do that, you need to tell Laravel which disk to use when uploading the file. Basically change your code to this:
Storage::disk('public')->put($fileName, file_get_contents($file), 'public');