Laravel 5.4 Error: NotReadableException: Image source not readable - laravel

I'm trying to create multiple copies of profile pic in different sizes when a profile is created. But I am constantly getting this error:
" NotReadableException: Image source not readable"
Can somebody point me what I'm missing in my below code:
public function updateprofile(UserProfileRequest $request){
$user_id = Auth::User()->id;
$profile = UserProfile::where('user_id','=',$user_id)->first();
$profile->fullname = $request->fullname;
if ($request->hasFile('img')) {
if($request->file('img')->isValid()) {
$types = array('_original.', '_32.', '_64.', '_128.');
$sizes = array( '32', '64', '128');
$targetPath = 'public/uploads/'.$user_id;
try {
$file = $request->file('img');
$ext = $file->getClientOriginalExtension();
$fName = time();
$original = $fName . array_shift($types) . $ext;
Storage::putFileAs($targetPath, $file, $original);
foreach ($types as $key => $type) {
$newName = $fName . $type . $ext;
Storage::copy($targetPath . $original, $targetPath . $newName);
$newImg = Image::make($targetPath . $newName);
$newImg->resize($sizes[$key], null, function($constraint){
$constraint->aspectRatio();
});
$newImg->save($targetPath . $newName);
}
$profile->img = 'public/uploads/'.$user_id;
} catch (Illuminate\Filesystem\FileNotFoundException $e) {
}
}
}
$profile->save();}

I had the same issue i ran this command and it worked
php artisan storage:link
This command creates a storage directory under the public folder.
Also use public path function to get the public path
$targetPath = public_path('storage/uploads/'. $user_id);
The 'storage' used inside the laravel public_path() function is used to get the storage main folder.

If I'm not mistaken, the path which is provided should be the absolute filepath on your server. For example instead of:
$targetPath = 'public/uploads/'.$user_id;
Use (your actual path will vary depending on your configuration)
$targetPath = '/var/www/sitename/public/uploads/'.$user_id;
Laravel also contains a helper function called public_path() which can be used to obtain the "fully qualified path to the public directory". This would allow you to use something such as:
$targetPath = public_path('uploads/'. $user_id);
Also, on this line, do not forget to place a slash before the new filename:
$newImg = Image::make($targetPath . '/' . $newName);
I would also confirm that the user executing the script (if apache or nginx usually www-data unless altered) has write permissions to your public/uploads/ directory

Finally, I got it working. I made following changes to my code:
Use the full OS path as suggested by commanderZiltoid for the destination path.
Don't use Storage::putFileAs method to save the file. So, remove this line: Storage::putFileAs($targetPath, $file, $original);
Don't use Storage::copy() to copy the file, so, remove this line:
Storage::copy($targetPath . $original, $targetPath . $newName);
For points 2 and 3, use Image::make($file->getRealPath()); This will create the file and remember the path where the file was created. Image->resize method will use this path later.
In the end, save the relative path in the database, as here: $profile->img = 'storage/uploads/'.$user_id.'/img/profile/'.$fName. Since we'll use {{ asset($profile->img) }}, it's necessary to save only the relative path and not the absolute OS path.
if($request->hasFile('img')) {
if($request->file('img')->isValid()) {
$types = array('_original.', '_32.', '_64.', '_128.');
$sizes = array( array('32','32'), array('64','64'), array('128','128'));
$targetPath = '/Users/apple/Documents/_chayyo/chayyo/storage/app/public/uploads/'.$user_id.'/img/profile/';
try {
$file = $request->file('img');
$ext = $file->getClientOriginalExtension();
$fName = time();
$o_name = $fName . array_shift($types) . $ext;
$original = Image::make($file->getRealPath());
$original->save($targetPath . $o_name);
foreach ($types as $key => $type) {
$newName = $fName . $type . $ext;
$newImg = Image::make($file->getRealPath());
$newImg->resize($sizes[$key][0], $sizes[$key][1]);
$newImg->save($targetPath . $newName);
}
$profile->img = 'storage/uploads/'.$user_id.'/img/profile/'.$fName;
}
catch (Illuminate\Filesystem\FileNotFoundException $e) {
}
}
}

Related

Cannot move image/files temp to public directory Laravel 9

I am trying to upload an image in Laravel. Getting the following error:
"message": "Could not move the file \"C:\\xampp\\tmp\\php84AA.tmp\" to \"F:\\bvend\\bvend-web\\public\\uploads/products\\bvend-product-1666274539.jpg\" (move_uploaded_file(): Unable to move "C:\\xampp\\tmp\\php84AA.tmp" to "F:\\bvend\\bvend-web\\public\\uploads/products\\bvend-product-1666274539.jpg").",
"exception": "Symfony\\Component\\HttpFoundation\\File\\Exception\\FileException",
"file": "F:\\bvend\\bvend-web\\vendor\\symfony\\http-foundation\\File\\UploadedFile.php",
"line": 177,
"trace": [ .... ]
My code is given below:
public function uploadImage($image, $image_path)
{
$path = config('global.' . $image_path . '_image_path');
file_exists($image) && unlink($image);
$image_name = 'bvend-' . $image_path . '-' . time() . '.' . $image->getClientOriginalExtension();
$image->move($path, $image_name); // $path: public_path('uploads/products')
return $image_name;
}
I understand its a simple issue but still no clue where it causing issue.
Edit
#WahidulAlam Please, try removing file_exists($image) && unlink($image);
– steven7mwesigwa - https://stackoverflow.com/posts/comments/130904221?noredirect=1
#WahidulAlam You're essentially deleting the temporary file/image before its copied or moved.
– steven7mwesigwa - https://stackoverflow.com/posts/comments/130904261?noredirect=1
ah this is the catch !! thanks a lot.
– Wahidul Alam - https://stackoverflow.com/posts/comments/130904399?noredirect=1
Specifying A File Name
If you do not want a filename to be automatically assigned to your
stored file, you may use the storeAs method, which receives the
path, the filename, and the (optional) disk as its arguments:
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
You may also use the putFileAs method on the Storage facade, which
will perform the same file storage operation as the example above:
$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);
Solution
public function uploadImage(\Illuminate\Http\UploadedFile $image, $image_path)
{
return $image->storePubliclyAs(
config('global.' . $image_path . '_image_path'),
'bvend-' . $image_path . '-' . time(),
["disk" => "public"]
);
}
Addendum
Don't forget to create a symbolic link from public/storage to storage/app/public. I.e:
php artisan storage:link.
The Public Disk
Once a file has been stored and the symbolic link has been created,
you can create a URL to the files using the asset helper:
echo asset('storage/file.txt');
In Summary
$savedPath = $request->file("***REQUEST-INPUT-IMAGE-NAME-HERE***")->storePubliclyAs(
"***IMAGE-PATH-HERE***",
"***CUSTOM-FILENAME-HERE***",
["disk" => "public"]
);
I am using this methodology in Laravel 9.
try this:
public function uploadImage($image, $image_path)
{
// $path = config('global.' . $image_path . '_image_path');
file_exists($image) && unlink($image);
$image_name = 'bvend-' . $image_path . '-' . time() . '.' . $image->getClientOriginalExtension();
//$image->move($path, $image_name); // $path: public_path('uploads/products')
$image->move(public_path('/images'), $image_name);
return $image_name;
}

How to Save File in storage folder with Original name?

I want to store an uploaded file with its original client name in the storage folder. What do I need to add or change in my code?Any help or recommendation will be greatly appreciated
Here my Controller
public function store(Request $request) {
$path = "dev/table/".$input['id']."";
$originalName = $request->file->getClientOriginalName();
$file = $request->file;
Storage::disk('local')->put($path . '/' . $originalName, $request->file);
}
Edit: I know how to get the originalClientName. the problem is storing the file in the folder using the original name, not the hash name. It doesn't store in the file in the original it makes a new folder instead here is the output "dev/table/101/Capture1.PNG/xtZ9iFoJMoLrLaPDDPvc4DMJEXkRL3R4qWOionMC.png" what I trying to get is "dev/table/101/Capture1.PNG"
I have tried to use StoreAs Or putFileAs but the method is undefined
I managed to figure out how to store it with a custom name, for those who want to know how to do it here is the code
$id = $input['id'];
$originalName = $request->file->getClientOriginalName();
$path = "dev/table/$id/".$originalName;
Storage::disk('local')->put($path, file_get_contents($request->file));
public function store(Request $request) {
$originalName = $request->file->getClientOriginalName();
$extension = $request->file->getClientOriginalExtension();
$path = "dev/table/" . $input['id'] . "/" . $originalName . "." . $extension;
$file = $request->file;
Storage::disk('local')->put($path, $file);
}
To get the original file name you can use this in your ControllerClass:
$file = $request->file->getClientOriginalName();
To get additional the extension you can use this Laravel Request Method:
$ext = $request->file->getClientOriginalExtension();
Then you can save with:
$fileName = $file.'.'.$ext;
$request->file->storeAs($path, $fileName);
// or
Storage::disk('local')->put($path . '/' . $fileName , $request->file);
You can save files using storage with the default name using putFileAs function instead of put which allow take third param as a file name
$path = "dev/table/101/";
$originalName = request()->file->getClientOriginalName();
$image = request()->file;
Storage::disk('local')->putFileAs($path, $image, $originalName);
Update
You can do something like this with put,
Storage::disk('local')->put($path.$originalName, file_get_contents($image));
I tried to manage like this;
$insurance = $request->file('insurance_papers');
$insuranceExtention = $insurance->getClientOriginalExtension();
$path = "public/files/" . $carrier->id . "/insurance_papers." . $insuranceExtention;
Storage::disk('local')->put($path, file_get_contents($insurance));
You can try this, this is work for me
if ($request->hasFile('attachment')) {
$image = $request->file('attachment');
$imageName = time() . '.' . $image->getClientOriginalExtension();
$path = "foldername/".$imageName;
Storage::disk('public')->put($path, file_get_contents($image));
}

How to set a dynamic path for ZipArchive addFile

EDIT
Problem solved. Had to update my filesystems config.
I want to create a zip file including all invoices which have been generated before. The problem is, if I am trying to do it with laravels storage url() or get() function, ZipArchive can not find the files.
I tried to solve it with storage_path(), ->url(), ->get() but none of them worked. It only works if I am typing the path to the files.
This is how it looks right now and it works.
$invoiceZipFileName = Carbon::now()->toDateString() . "_invoices.zip";
$zip = new ZipArchive();
$zip->open($invoiceZipFileName, ZipArchive::CREATE);
$files->each(function ($item, $key) use ($zip, $disk) {
$zip->addFile("storage/invoices/" . $item, $item);
});
$zip->close();
What I want to achieve is something like that:
$invoiceZipFileName = Carbon::now()->toDateString() . "_invoices.zip";
$zip = new ZipArchive();
$zip->open($invoiceZipFileName, ZipArchive::CREATE);
$files->each(function ($item, $key) use ($zip, $disk) {
$zip->addFile($disk->get($item), $item);
});
$zip->close();
or:
$invoiceZipFileName = Carbon::now()->toDateString() . "_invoices.zip";
$zip = new ZipArchive();
$zip->open($invoiceZipFileName, ZipArchive::CREATE);
$files->each(function ($item, $key) use ($zip, $disk) {
$zip->addFile($disk->url($item), $item);
});
$zip->close();
or:
$invoiceZipFileName = Carbon::now()->toDateString() . "_invoices.zip";
$zip = new ZipArchive();
$zip->open($invoiceZipFileName, ZipArchive::CREATE);
$files->each(function ($item, $key) use ($zip, $disk) {
$zip->addFile(storage_path("invoices") . "/" . $item, $item);
});
$zip->close();
These are the error messages (each was in another case, they don't occur together) I get:
exception: "Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException"
file: "C:\xampp\htdocs\invoicing\vendor\symfony\http-foundation\File\File.php"
line: 36
message: "The file "2019-10-02_invoices.zip" does not exist"
exception: "ErrorException"
file: "C:\xampp\htdocs\invoicing\app\Http\Controllers\Api\V1\InvoiceController.php"
line: 211
message: "ZipArchive::close(): Failure to create temporary file: No error"
++++ EDIT ++++
Problem solved. Had to update my filesystems config.
Using the below link setup Zipper package into your laravel project.
https://github.com/Chumper/Zipper
after completion of Zipper package setup use the below code into your respected controller.
$files = glob($image_dir_media . $file_new_name);
$date = new DateTime();
$zip = $date->format('Y-m-d') . '_invoices.zip';
\Zipper::make(public_path() . '/media/' . $zip)->add($files)->close();
Thanks
PHPanchal

Laravel deploy: storage image doesn't work correctly

After deploying my laravel project from local to Apache web server, all works correctly except images link. Here the code:
Images are stored in:
storage/app/public/photos
after i've run command:
php artisan storage:link
Images are linked at:
public/storage/photos
Controller:
if ($request->hasFile('photo')) {
$extension = $request->file('photo')->getClientOriginalExtension();
$file = $request->file('photo');
$photo = $file->storeAs('public/photos', 'foto-' . time() . '.' . $extension);
$user->photo = $photo;
$user->save();
}
Images are uploaded correctly on storage/app/public/photos and correctly linked in public/storage/photos but it doesn't display on frontend.
in blade, i've tried to use Storage::url to retrieve the path
{{Storage::url($user->photo)}}
and asset()
{{asset($user->photo)}}
in both cases, image doesn't exist
The public path of image is:
http://mywebsite.com/storage/photos/foto-1522914164.png
You should Use url function to show your image like below way.
url($user->photo);
I'd suggest to change the controller code as follows:
if ($request->hasFile('photo')) {
$extension = $request->file('photo')->getClientOriginalExtension();
$file = $request->file('photo');
$photoFileName = 'foto-' . time() . '.' . $extension;
$photo = $file->storeAs('public/photos', $photoFileName);
$user->photo = 'photos/' . $photoFileName;
$user->save();
}
Then you can use {{asset($user->photo)}} in your blade.
on my webspace, it seems that the only way to display image correctly is to create a custom route that read and serve the image.
i'm solved like this:
i'm storing only image name in db:
if ($request->hasFile('photo')) {
$extension = $request->file('photo')->getClientOriginalExtension();
$file = $request->file('photo');
$photoFileName = 'photo-' . $model->id . '.-' . time() . '.' . $extension;
$photo = $file->storeAs('public/photos', $photoFileName);
$store = $photoFileName;
}
then, i've create custom route that read images and display them:
Route::get('storage/{filename}.{ext}', function ($filename, $ext) {
$folders = glob(storage_path('app/public/*'), GLOB_ONLYDIR);
$path = '';
foreach ($folders as $folder) {
$path = $folder . '/' . $filename . '.' . $ext;
if (File::exists($path)) {
break;
}
}
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;
});
in blade, i'm using Storage to display image:
{{ Storage::url($photo->photo) }}}

Image is not saving into the defined folder

I am now troubling with this small error. I have a module which is using to upload images. Now this is my code for saving the file. It is defined in saveAction() method of controller.
<?php
/*rest part*/
$postData = $this->getRequest()->getPost();
if(isset($_FILES['banner_img_1']['name']) and (file_exists($_FILES['banner_img_1']['tmp_name'])))
{
try
{
$uploader = new Varien_File_Uploader('banner_img_1'); $uploader->setAllowedExtensions(array('jpg','jpeg','gif','png'));
$uploader->setAllowRenameFiles(false);
$uploader->setFilesDispersion(false);
$path = Mage::getBaseDir('media') . DS . 'banner' . DS ;
$uploader->save($path, $_FILES['banner_img_1']['name']);
$postData['banner_img_1'] = $_FILES['banner_img_1']['name'];
}
catch(Exception $e)
{
}
}
else
{
if(isset($postData['banner_img_1']['delete']) &&
$postData['banner_img_1']['delete'] == 1)
$postData['image_main'] = '';
else
unset($postData['banner_img_1']);
}
However this is not storing my image in media/banner folder. When I use path as
<?php
$path = Mage::getBaseDir('media') . DS ;
it saves image in media folder. I dont know the reason why it happens like this. when I print the $path variable, it currectly points towards media/banner folder. What is the error in my code? Please help me to solve this minor error. Thanks in advance..
Try this code in the try block {}
$path = Mage::getBaseDir('media') . DS . 'banner' . DS .'banner'.DS;
$uploader = new Varien_File_Uploader('banner_img_1');
$uploader->setAllowedExtensions(array('jpg','png','gif'));
$uploader->setAllowRenameFiles(false);
$uploader->setFilesDispersion(false);
$destFile = $path.$_FILES['banner_img_1']['name'];
$filename = $uploader->getNewFileName($destFile);
$uploader->save($path, $filename);
$post_data['banner_img_1']='banner/banner/'.$filename;

Resources