I am unable to delete the file (uploaded by the user) on calling the destroy method in the post controller.
I am able to upload the file to my drive that is
root/public/uploads/attachment
this is my filesystem
'uploads' => [
'driver' => 'local',
'root' => public_path('uploads'),
],
This is what i have tried in my controller
public function destroy(Post $post)
{
$post=Post::find($post->id);
Storage::disk('uploads')->delete($post->image);
$post->categories()->detach();
$post->tags()->detach();
$post->delete();
return redirect('admin/post')->with('message','Deleted Sucessfully');
}
I also have tried
unlink(public_path().'/uploads/'.$post->image);
But both actions gives the same results the post gets deleted but when i physically check the attachments folder the image is still present there
If you specify the Disk Then try it(Full Path of Image)..
Storage::disk('uploads')->delete(public_path().'/uploads/'.$post->image);
Or
Storage::delete($post->image);
And Must use
use Illuminate\Support\Facades\Storage;
You will need to use the full path to the file in order to delete it.
https://laravel.com/docs/5.8/filesystem#deleting-files
Try using the full path in Storage::disk('uploads')->delete($post->image);
Related
I'm learning laravel but I have problem now with the image,
I want it to save it in storage/app/public/avatar so I can show it, but it keep saving it in storage/app/avatar
I write this in the .env
FILESYSTEM_DRIVER=public
And then I generate the storage link
php artisan storage:link
but still the same, every time I upload a photo it saving it in storage/app/avatar
Anyone can help me?
In filesystems.php
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
Here :
$attributes['avatar'] = request('avatar')->store('public/avatars');
In USer.php
public function getAvatarAttribute($value)
{
return asset($value);
}
this method was working correctly when i was using a random avatar link,
but now it show nothing, i check my database and the link is there and it's right
public function getAvatarAttribute($value)
{
asset('storage/avatars/'.$image->name);
}
$attributes['avatar'] = request('avatar')->store('public/avatars');
In the controller, update method:
$user->update($attributes);
$user->password = Hash::make($user['password']);
$user->save();
return redirect($user->path());
In the show.blade
<img
src= "{{ $user->avatar }}"
alt=""
class="rounded-full mr-4 absolute"
style="width: 150px; left: calc(50% - 75px); top: 300px"
>
but the src become "(unknown)"
This looks more like a configuration cache issue as your filesystem looks properly configured.
The storage/app folder is the path of laravel's default disk (the local disk). Since you had specified to use public as the default disk in .env but your application is still using the local disk path, it looks like a cache issue
Try using
php artisan config:clear
And then attempt
request('avatar')->store('avatars');
If it was indeed a cache issue, then the file should be stored in the storage/app/public folder.
To get the full path to the image, use
Storage::url('avatar/'.$user->avatar);
So in the accessor, use
public function getAvatarAttribute($value)
{
return Storage::url('avatar/'.$value);
}
Using asset() to get the path to the file is not recommended because if some day you wish to switch storage to the cloud (S3, or any other storage. basically, you want to not use the storage folder of your application), then the asset() will no longer give you the correct path and you'd need to change it everywhere. But when using the storage facade, all you need to do is change it in the filesystems.php
Also, just to test it yourself, you could also specify the disk when storing by specifying the disk as the second argument to the store method
request('avatar')->store('avatars', 'public');
Storage::disk('public')->url('avatar/'.$user->avatar);
Also, don't forget to delete public/storage folder
and then re-run
php artisan config:clear
This is important
php artisan storage:link
Change "FILESYSTEM_DRIVER=public" to
FILESYSTEM_DISK=public
Or remove that line completely and directly set public folder as default disk in filesystems.php as follows:
'default' => env('FILESYSTEM_DISK', 'public'),
The store method stores the files in storage/app directory. That's why your code is storing the image in storage/app/avatars
request('avatar')->store('avatars');
This will place it under storage/app/public/avatars
request('avatar')->store('public/avatars');
To show it
asset('storage/avatars/`.$image->name)
I'm using Dingo/API and this is a transformer that returns me data
return [
'id' => $site->id,
'path' => asset($site->path),
'siteLink' => $site->site_link,
'features' => $features,
];
Generated link looks good, however when I try to access it from my Angular app it's said that
Failed to load resource: the server responded with a status of 404 (Not Found)
http://api.example.com/public/thumbnails/ySOSYhaCCRcH3t9agsco3ToUwoHxMZJ3r1PhEHlM.jpeg
Are you sure that your image stored in public/public folder?
asset() helper generate a asset path from public folder. So, in your property $site->path you getting a path to your image like 'public/yourimage.jpeg'. Try to remove 'public' from your $site->path.
The solution.
In filesystems.php local disk was specified as a default disk. According to docs local disk is supposed to be invisible for public and stored inside storage/app. Thus I was trying to save my file using local disk and accessing it with path public/....
Option #1
Change in filesystems.php default disk to public and use Storage::url() to get url to image.
Option #2
Use $file->store('path', 'public') and Storage::disk('public')->url('path')
So that used disk is specified explicitly.
The given path will contain link close to http://example.com/storage/path.
I have created a designated location to store all the uploaded images in public dir like this:
and I have the default config/filesystem.php for public driver like this:
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
Within my repository, I am trying to save the uploaded image like this:
// ... snipped
if (array_key_exists('logo', $validated)) {
$logoPath = $validated['logo']->store(
'uploads/logos',
'public'
);
$company->logo = url($logoPath);
}
$company->save();
In the database, I can see the value of logo field for the company record like this: http://my-app.local/uploads/logos/3hlsAhnnIPjd4zhdpfhvKw4tqDkpcCz23NczwhVM.png
However, the public/uploads/logos dir is empty. Any idea what might be wrong here? Am I supposed to use the ->move() method on the UploadedFile instead of ->store()?
You can use an alternative method for uploading images in your public directory.
$request->validate([
'logo' => 'image|required',
]);
if($request->hasFile('logo')){
$company->logo = $request->image->move('uploads/logo', $request->logo->hashName());
}
$company->save()
Actually, yes, it was your mistake, but not the one you just found. By default laravel local storage points to storage/app/public directory, because laravel wants you to act professionally and store all uploaded files in storage, not in some kind of public directory. But then you would ask - how on earth user should access non-public storage directly? And there is a caught - php artisan storage:link command. It creates symbolic link from public directory to storage directory (storage/app/public -> public/storage). This is mostly because of deployments and version management.
The server which I'm hosting my website does not support links so I cannot run the php artisan storage:link to link my storage directory into the public directory. I tried to remake the disk configuration in the filesystems.php to directly reference the public folder but it didn't seems to work either. Is there a way to upload a file using Laravel libraries directly into the public folder or will I have to use a php method?
You can create a new storage disc in config/filesystems.php:
'public_uploads' => [
'driver' => 'local',
'root' => public_path() . '/uploads',
],
And store files like this:
if(!Storage::disk('public_uploads')->put($path, $file_content)) {
return false;
}
You can pass disk to method of \Illuminate\Http\UploadedFile class:
$file = request()->file('uploadFile');
$file->store('toPath', ['disk' => 'public']);
or you can create new Filesystem disk and you can save it to that disk.
You can create a new storage disk in config/filesystems.php:
'my_files' => [
'driver' => 'local',
'root' => public_path() . '/myfiles',
],
in controller:
$file = request()->file('uploadFile');
$file->store('toPath', ['disk' => 'my_files']);
You should try this hopping you have added method="post" enctype="multipart/form-data" to your form. Note that the public path (uploadedimages) will be moved to will be your public folder in your project directory and that's where the uploaded images will be.
public function store (Request $request) {
$imageName = time().'.'.$request->image->getClientOriginalExtension();
$request->image->move(public_path('/uploadedimages'), $imageName);
// then you can save $imageName to the database
}
inside config/filesystem.php, add this :
'public_uploads' => [
'driver' => 'local',
'root' => public_path(),
],
and in the controller
$file = $request->file("contract");
$ext = $file->extension();
$filename = $file->storeAs('/contracts/', $contract->title.'.' . $ext,['disk' => 'public_uploads']);
I figured out the fix to this issue , in the config/filesystem.php add this line 'default' => 'public', in my case that fixed for me.
The most flexible is to edit .env file:
FILESYSTEM_DRIVER=public
In addition to every answer there, I would suggest to add another protection layer because it's a public folder.
For every file that you will have in your public folder that requires protection, do a route that will verify access to them, like
/files/images/cat.jpg
and route that looks like /files/images/{image_name} so you could verify the user against given file.
After a correct validation you just do
return response($full_server_filepath, 200)->header('Content-Type', 'image/jpeg');
It makes a work little harder, but much safer
The recommended way is to symlink the storage from the public directory.
To make these files accessible from the web, you should create a
symbolic link from public/storage to storage/app/public. Utilizing
this folder convention will keep your publicly accessible files in one
directory that can be easily shared across deployments when using zero
down-time deployment systems like Envoyer.
To create the symbolic link, you may use the storage:link Artisan
command:
Step 1: change setting in Filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => public_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
Step 2: in Controller: Store file like this:
'indoc_file' => $request->indoc_file->store('app/file'),
Step 3: Go to file .ENV and change the Config like this:
FILESYSTEM_DRIVER=public
After that your file Location will be saved in Project like this:
Project\public\app\public\app\file
if you want to download file able do this on your view page:
<i class="fa fa-download"></i>
as alternative,
let laravel set the file stored in /storage/app folder.
if we want to read the file, just use like $publicPath = '../storage/app/'.$path;
There is an issue related to my laravel 5 web application regarding the file deletion.
I want to delete an entry from my table with corresponding image file.
Here is my table structure.
Schema::create('master_brands',function($table){
$table->increments('pk_brand_id');
$table->string('brand_name');
$table->string('brand_logo');
$table->timestamps();
});
I added 3 brands to db and storing image path in brand_logo field like : (/uploads/masters/logocatagory_Computers & IT.png).
When deleting the record from database I want to delete the image file from uploads folder also.
But the File was not deleting when I performing delete action.
here is my delete controller.
public function branddelete($id)
{
$filename = DB::table('master_brands')->where('pk_brand_id', $id)->get();
$filname = url()."/app".$filename[0]->brand_logo;
File::delete($filname); // http://localhost/genie-works/devojp/app//uploads/masters/logocatagory_Computers & IT.png
}
The file is exist in my directory and the directory having 777 permission. !!
I also tried the Storage class to delete file.But there is no way !!!..
How can I solve this issue? Any Ideas... :(
You are doing it the wrong way. You can't possibly delete a file from URL, you must provide file PATH not URL
Edited
Assuming the file you wish to delete is located in public/uploads/masters/logocatagory_Computers you could do this:
public function branddelete($id)
{
$filename = DB::table('master_brands')->where('pk_brand_id', $id)->get();
$filname = $filename[0]->brand_logo;
//example it.png, which is located in `public/uploads/masters/logocatagory_Computers` folder
$file_path = app_path("uploads/masters/logocatagory_Computers/{$filname}");
if(File::exists($file_path)) File::delete($file_path);
}
If you have the file out Storage/app/ , Storage:: does not work, change the /Config/Filesystems.php try put your 'local' at base_path() and comment default storage_path(),
'disks' => [
'local' => [
'driver' => 'local',
'root' => base_path(),
// 'root' => storage_path('app'),
],
Then in Controller
use Illuminate\Support\Facades\Storage;
Then in public funtion use Storage Model
$path= 'uploads/masters/';
Storage::delete($path . $filname);
In Laravel 5.1. When using the local driver, note that all file operations are relative to the root directory defined in your configuration file. By default, this value is set to the storage/app directory. Therefore,
the following method would store a file in storage/app/file.txt:
Storage::put('file.txt', 'Contents');
this would delete file.txt in storage/app
Storage::delete('file.txt');
If you want to change the root directory,take 'storage/app/uploads/' for example , you could set the filesystem.php as following :
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/uploads/'),
],
...
then this following method would store a file in storage/app/uploads/file.txt:
Storage::put('file.txt', 'Contents');
this would delete file.txt in storage/app/uploads directory.
Storage::delete('file.txt');
Something that took me quite some time to figure out today:
In case you're trying to delete a list of files that are wrapped in Laravel's own Collection wrapper, you might need to call ->all() to get the underlying array instance:
// The following is an example scenario
$files = Storage::list('downloads');
$collection = collect($files)->filter(function ($file) {
return str_contains($file, 'temp');
});
Storage::delete($collection->all()); // Note the "all()" call here