Delete file from a specific directory in Laravel local storage - php

I am storing files at local storage. So, in /storage/app/public directory.
I am storing my files in /storage/app/public/userId/images ;
I used php artisan storage:link , so I can access that files in view, having a shortcut to this folder in /public/storage/userId/images
Inside that path I have 2 images - test.jpg and test2.jpg
I can't find a response at Laravel documentation, how to delete file test.jpg from /public/storage/userId/images
I tried in this way :
$path = 'public/' . $id . '/diploma';
$files = Storage::files($path);
return $files;
It returns me :
[
"public/303030/images/test.jpg"
"public/303030/images/test2.jpg"
]
Now, how can I call Storage::delete('test.jpg') on that array?

There is multiple ways to delete image
//In laravel
File::delete($image);
//for specific directory
File::delete('images/' . 'image1.jpg');
and other way (Simple PHP)
//Simple PHP
unlink(public_path('storage/image/delete'));
and if you want to delete more than 1 images than
Storage::delete(['file1.jpg', 'file2.jpg']);
//or
File::delete($image1, $image2, $image3);
for more detail about Delete File in Laravel

Use Storage::delete(). The delete method accepts a single filename or an array of files to remove from the disk.
Storage::delete($file_to_delete);
May be you want to do something like-
$files = Storage::files($path);
Storage::delete($files);

use File;
public function destroy($id,$src)
{
File::delete('file/' . $src);
fileModel::find($id)->delete();
return back()->withErrors("");
}
if you store your image public/file folder you can delete like this . it will work . in the $src just pass the file name .
Example: $src = example.png;

Related

laravel missing file after image upload

I want to upload a image to a sub directory (public/uploads). after submit it returns successful but it doesn't save the image
public function storeMedia(Request $request)
{
$file = $request->file('productImage');
$name = trim($file->getClientOriginalName());
$folder = uniqid() . '_' . now()->timestamp;
$file->storeAs('uploads/'.$folder, $name, ['disk' => 'public']);
return $folder;
}
it returns 60dc27eb0eb92_1625040875 which is want I need but I can't find the uploaded file
By default laravel stores file in storage folder. If you want your image file need to be accessible publicly then you need to create symbolic link.
refer this Laravel public disk
put the folder link path in config/filesystems.php
public_path('storage/uploads') => storage_path('app/public/uploads')
Run artisan command to create symbolic link
php artisan storage:link
Here you can refer my another detailed answer for symbolic link uploading file publicly accessible
On your config/filesystems.php file, search for public_uploads and update the root to public_path() . '/uploads' and that must do the trick

Why is Laravel renaming the file extension of the image that I upload? [duplicate]

I am allowing users to upload any kind of file on my page, but there might be a clash in names of files. So, I want to rename the file automatically, so that anytime any file gets uploaded, in the database and in the folder after upload, the name of the file gets changed also when other user downloads the same file, renamed file will get downloaded.
I tried:
if (Input::hasFile('file')){
echo "Uploaded</br>";
$file = Input::file('file');
$file ->move('uploads');
$fileName = Input::get('rename_to');
}
But, the name gets changed to something like:
php5DEB.php
phpCFEC.php
What can I do to maintain the file in the same type and format and just change its name?
I also want to know how can I show the recently uploaded file on the page and make other users download it??
For unique file Name saving
In 5.3 (best for me because use md5_file hashname in Illuminate\Http\UploadedFile):
public function saveFile(Request $request) {
$file = $request->file('your_input_name')->store('your_path','your_disk');
}
In 5.4 (use not unique Str::random(40) hashname in Illuminate\Http\UploadedFile). I Use this code to ensure unique name:
public function saveFile(Request $request) {
$md5Name = md5_file($request->file('your_input_name')->getRealPath());
$guessExtension = $request->file('your_input_name')->guessExtension();
$file = $request->file('your_input_name')->storeAs('your_path', $md5Name.'.'.$guessExtension ,'your_disk');
}
Use this one
$file->move($destinationPath, $fileName);
You can use php core function rename(oldname,newName) http://php.net/manual/en/function.rename.php
Find this tutorial helpful.
file uploads 101
Everything you need to know about file upload is there.
-- Edit --
I modified my answer as below after valuable input from #cpburnz and #Moinuddin Quadri. Thanks guys.
First your storage driver should look like this in /your-app/config/filesystems.php
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'), // hence /your-app/storage/app/public
'visibility' => 'public',
],
You can use other file drivers like s3 but for my example I'm working on local driver.
In your Controller you do the following.
$file = request()->file('file'); // Get the file from request
$yourModel->create([
'file' => $file->store('my_files', 'public'),
]);
Your file get uploaded to /your-app/storage/app/public/my_files/ and you can access the uploaded file like
asset('storage/'.$yourModel->image)
Make sure you do
php artisan storage:link
to generate a simlink in your /your-app/public/ that points to /your-app/storage/app/public so you could access your files publicly. More info on filesystem - the public disk.
By this approach you could persists the same file name as that is uploaded. And the great thing is Laravel generates an unique name for the file so there could be no duplicates.
To answer the second part of your question that is to show recently uploaded files, as you persist a reference for the file in the database, you could access them by your database record and make it ->orderBy('id', 'DESC');. You could use whatever your logic is and order by descending order.
You can rename your uploaded file as you want . you can use either move or storeAs method with appropiate param.
$destinationPath = 'uploads';
$file = $request->file('product_image');
foreach($file as $singleFile){
$original_name = strtolower(trim($singleFile->getClientOriginalName()));
$file_name = time().rand(100,999).$original_name;
// use one of following
// $singleFile->move($destinationPath,$file_name); public folder
// $singleFile->storeAs('product',$file_name); storage folder
$fileArray[] = $file_name;
}
print_r($fileArray);
correct usage.
$fileName = Input::get('rename_to');
Input::file('photo')->move($destinationPath, $fileName);
at the top after namespace
use Storage;
Just do something like this ....
// read files
$excel = $request->file('file');
// rename file
$excelName = time().$excel->getClientOriginalName();
// rename to anything
$excelName = substr($excelName, strpos($excelName, '.c'));
$excelName = 'Catss_NSE_'.date("M_D_Y_h:i_a_").$excelName;
$excel->move(public_path('equities'),$excelName);
This guy collect the extension only:
$excelName = substr($excelName, strpos($excelName, '.c'));
This guy rename its:
$excelName = 'Catss_NSE_'.date("M_D_Y_h:i_a_").$excelName;

Laravel 6 Storage results in a 404 error when trying to fetch files

I have tried to setup an upload script in Laravel and have followed the instructions in the docs.
I created a Symlink using the Laravel script and it looks like the following
storage -> /Users/username/Sites/switch/storage/app/public
The problem arrives when I go to upload the image and then get result of the image url in return. As you can see to match the symlink I set the folder to be public below.
$path = $request->file('manufacturer_image_name')->store('public');
echo asset($path);
and this returns
http://127.0.0.1:8000/public/XxIX7L75cLZ7cf2xzejc3E6STrcjfeeu3AQcSKz1.png
the problem is this doesn't work and throws a 404 but if I manually change the url from "public" to "storage" it will find the image.
http://127.0.0.1:8000/storage/XxIX7L75cLZ7cf2xzejc3E6STrcjfeeu3AQcSKz1.png
Shouldn't
echo asset($path);
be returning a url containing storage instead of public?
assett($path) is for generating a URL for assets that are just in the public folder, things like the Mix generated CSS and JS files. If you user Laravel Storage to save the file, you also have to use Laravel storage to generate the file URL.
Storage::url('file.jpg');
Well, there are a lot of ways to do that, pick anyone which fits you best.
// using storage_path helper
storage_path('public/' . $filename);
// you could make a double-check with File::exist() method
$path = storage_path('public/' . $filename);
if (!File::exists($path)) {
abort(404);
}
// using asset helper
asset('storage/your_folder/image.png');
// using url helper
url('storage/your_folder/image.png');
// using Storage facade
Storage::url($photoLink)
Here is the simplest and exact thing for your issue
if(!empty($request->file('manufacturer_image_name'))){
$path = storage_path('public/image/');
$image_path = Storage::disk('public')->put('manufacturer_image_name', $request->file('manufacturer_image_name'));
//Assuming you have a model called Manufacturer and created $manufacturer = new Manufacturer()
$manufacturer->manufacturer_image_name = isset($image_path) ? "storage/".$image_path : "";
}
Thanks for the help, I discovered this answer the fits nearly perfectly what I am after. Laravel: Storage not putting file inside public folder
This was what I ended up with.
if($request->file('manufacturer_image_name')){
$path = Storage::disk('public')->put('logo', $request->file('manufacturer_image_name'));
echo $path;
}
$path now returns "logo/filename.ext" instead of "public/ or storage/" so I can store this directly in the db.

How to store multiple uploaded files with Laravel's Storage Facade

Currently I have a project that is running Laravel 5.8 and I am trying to use a form that allows user's to upload their own images to the site and store it in the public folder. When trying to use the Storage facade with the 'put' method, a path gets returned but the images do not actually get stored.
if ($request->hasfile('images')) {
foreach ($request->file('images') as $file) {
$path = Storage::disk('public')->put('images', $file);
echo $path;
}
}
This is the code I am trying to use. The path gets echo'd as it should and I have not made any changes to the filesystem config. In the form, the input field images allows for submitting multiple files and the form does hasenctype="multipart/form-data". The $file variable also contains an instance of Illuminate\Http\UploadedFile.
The previous code I used which did work was:
if ($request->hasfile('images')) {
foreach ($request->file('images') as $file) {
$file->move(public_path('images'), $file->getClientOriginalName());
}
}
I would be okay with using my previous code if Laravel can give it a unique file name on upload but what would be causing my code with the Storage facade to not save the images properly? Does the put function just not work like that or is there something I am overlooking?
Edit:
So I realise the images were in fact saving correctly as they should be. I was looking inside the public folder rather than the storage folder which is why my second code example 'worked' but not the first. I realise when using the Storage facade I need to make use of Symbolic linking if I want to access these files on the web.
You need to also make sure you have created the symbolic link on your Ubuntu server or Windows development machine to the storage folder.
Windows you can use : mklink /j /path/to/laravel/public/youfolder /path/to/laravel/storage/youfolder
Ubuntu: ln -s /path/to/laravel/public/youfolder /path/to/laravel/storage/youfolder
To check & set you can also use use php artisan storage:link
Hope this helps
if ($request->hasfile('images')) {
foreach ($request->file('images') as $file) {
$path = Storage::disk('public')->put('images', $file);
$new_file_name = time() . "_" . uniqid() . "_" . $file->getClientOriginalName();
$path = Storage::disk('public')->put($new_file_name, file_get_contents($file));
echo $path;
}
}

Cannot save image intervention image. NotWritableException in Image.php line 138

Im trying to save a manipulated image which i will them push to s3.
My code that works This code saves the image directly within the public folder*
public function store(Filesystem $filesystem)
{
$request = Input::all();
$validator = Validator::make($request, [
'images' => 'image'
]);
if ($validator->fails()) {
return response()->json(['upload' => 'false']);
}
$postId = $request['id'];
$files = $request['file'];
$media = [];
$watermark = Image::make(public_path('img/watermark.png'));
foreach($files as $file) {
$image = Image::make($file->getRealPath());
$image->crop(730, 547);
$image->insert($watermark, 'center');
$image->save($file->getClientOriginalName());
}
}
What i would like to achieve is to be able to save it within a folder of it's own. Firstly what is the best place to store an image for a blog post, within the storage of public folder? But anyway when i do this:
$image->save('blogpost/' . $postId . '/' . $file->getClientOriginalName());
// Or this
$image->save(storage_path('app/blogpost/' . $postId . '/' . $file->getClientOriginalName()));
I get the error:
folder within public
NotWritableException in Image.php line 138: Can't write image data to
path (blogpost/146/cars/image.jpg)
or
storage path
NotWritableException in Image.php line 138: Can't write image data to
path /code/websites/blog/storage/app/blogpost/146/image.jpg
I've tried
cd storage/app/
chmod -R 755 blogpost
And it still wont work
Thank you for reading this
Ok so here is how i solved it, I made the directory first before storing,
Storage::disk('local')->makeDirectory('blogpost/' . $postId);
Once the folder is created i then go on to store the manipulated images like so:
$image->save(storage_path('app/blogpost/' . $postId . '/' . $imageName));
And then pushing the image to S3
$filesystem->put('blogpost/' . $postId . '/' . $imageName, file_get_contents(storage_path('app/blogpost/' . $postId . '/' . $imageName)));
This worked
You can solve it by casting the Intervation/Image variable to a data stream using function stream. Then use the Storage Laravel facade to save the image.
$img = Image::make('path-to-the-image.png')->crop(...)->insert->stream('jpg', 90)
Storage::put('where_I_want_the_image_to_be_stored.jpg', $img);
Laravel 5 needs permission to write to entire Storage folder so try following,
sudo chmod 755 -R storage
if 755 dont work try 777.
Am improving #Amol Bansode answer.
You are getting this error because $postId folder does not exist in the path you specified.
You could do it like this:
//I suggest you store blog images in public folder
//I assume you have created this folder `public\blogpost`
$path = public_path("blogpost/{$postId}");
//Lets create path for post_id if it doesn't exist yet e.g `public\blogpost\23`
if(!File::exists($path)) File::makeDirectory($path, 775);
//Lets save the image
$image->save($path . '/' . $file->getClientOriginalName());
In my case I migrated a project from Windows 10 to Parrot (Debian-Linux) and I had the same problem and turned out the slashes were backward slashes and Linux interpret them differently. Unlike Windows, it doesn't really matter.
//Windows Code:
$image_resize->save(public_path('\storage\Features/' .'Name'.".".'png'));
//Linux Code (Working):
$image_resize->save(public_path('storage/Features/' .'Name'.".".'jpg'));
I know the question is related to Laravel but I came across from making it to work with WordPress. If somebody is coming from WordPress world, this code works (I was getting the same 'cannot write' error) and changing directory permission would not work as the library probably needs the relative path (the code below is valid for direct installation of Intervention through composer into any PHP application, not Laravel per se)-
require 'vendor/autoload.php';
use Intervention\Image\ImageManager;
$manager = new ImageManager(array('driver' => 'imagick'));
$image = $manager->make('PUBLIC IMAGE URL/LOCAL IMAGE PATH');
$image->crop(20, 20, 40, 40);
$image->save(__DIR__ . '/img/bar.png');
in my case:
i double check my symlinks in filesystem.php in config folder in laravel
and remove all symlink then regenerate them
php artisan storage:link
in my case my fileName is not valid format for naming in windows but it worked on linux or docker
$make_name = date('Y-m-d-H:i:s') . hexdec(uniqid()) . '.' . $img->getClientOriginalExtension();
when I remove this date('Y-m-d-H:i:s') it worked as well
I have faced the same issue but 775 permission not sort it so I changed the write permission to the folder(also sub-folders) to 777 to get over this issue.

Categories