Storage Path not writeable in laravel with Intevention? - image

I'm getting a little confused here with this Storage VS Public paths in Laravel 5 > ... My understanding is one should use Storage:: instead of File:: for writing files to the Storage folder foresighting the use of cloud services like Amazon etc. So I am trying to put a jpg into a the storage/app folder using Intervention and this code:
public function apply(Request $request)
{
$user = Auth::user();
$path = '/users/'.$user->id;
if (!Storage::exists($path))
{
Storage::makeDirectory ($path, $mode = 0755, $recursive = false, $force = false);;
}
Image::make($request->file('image'))
->orientate()
->resize(600, null, function ($constraint) {
$constraint->aspectRatio();
})
->resizeCanvas(600, 600, 'center', false, 'ffffff')
->save($path.'/foo.jpg');
}
First of all I am not sure the !Storage::exists($path) will do anything as the API for storage tells it won't check for directories so how should I check if a Directory exists??
Second dd(is_writable($path)); return false, and indeed running that code results in
NotWritableException in Image.php line 143:
Can't write image data to path
error.
so how should this be done?

The "trick" that I used was manipulate the image directly in the temp path, and then save it in the storage folder using the Laravel storage method.
$tempFile = $request->file('image')->getRealPath();
Image::make($tempFile)
->resize(100, 100)
->save($tempFile); // Note that we are saving back to temporary path
// Now we can proceed and send the manipulated file to it's final destination
// in '/storage/app/public/uploads'
$path = $request->file('image')->storePublicly('public/uploads');

Related

Images not showing in update function using BackPack for Laravel

I´m saving images in my crud. The url is being stored in the DB correctly, however the image is not appearing when I try to edit the element. The image shows like this:
I'm using this mutator:
public function setImageAttribute($value)
{
$evidencia = "image";
$disk = "public";
$destination_path = "public/uploads/evidenciaQuejas";
// if the image was erased
if ($value==null) {
// delete the image from disk
\Storage::disk($disk)->delete($this->{$evidencia});
// set null in the database column
$this->attributes[$evidencia] = 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 = md5($value.time()).'.jpg';
// 2. Store the image on disk.
\Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
// 3. Save the path to the database
$this->attributes[$evidencia] = $destination_path.'/'.$filename;
}
}
Also, the folder that I created in the server to store the images ("public/uploads/evidenciaQuejas") says it has 0 archives inside even though the image is being stored without errors.
Could you help me please?

delete old image while updating the field

I am doing CRUD operations for images. when I am doing the update operation image gets updated but the old image doesn't delete. The following code updates only the file name in the database but I need to remove the old image from the destination folder too while updating else the folder size will become too large. Any ideas would be great. Here my code.
<input type="file" name="profileimage" value="{{ isset($editabout) ? $editabout->profileimage : '' }}" class="custom-file-input" id="exampleInputFile">
Here is my controller
public function update(updateAboutusProfile $request, AboutUs $about)
{
$data=$request->only(['profiletext']);
if($request->hasFile('profileimage')){
$profileimage = $request->profileimage->store('aboutus', 'public');
$oldimage = $about->profileimage;
Storage::delete($oldimage);
$data['profileimage'] = $profileimage;
}
$about->update($data);
toastr()->success('Profile updated successfully');
return redirect(route('about.index'));
//
}
What can be the error I need to resolve,
thank you
Try setting the disk you used to store the file
Storage::disk('public')->delete($oldimage);
Delete image from your server, you have to reference location of file in directory server, means you could not reference by url link to delete it.
Laravel file is locate in public folder.
Example: your files are located in public/images
$image_path = "/images/filename.ext"; // Value is not URL but directory file path
if(File::exists($image_path)) {
File::delete($image_path);
}
Enjoy ;)
You should save the path of the file to the database and then simply remove it using \Storage::delete() facade.
Store image using hash name
if($request->hasFile('profileimage')){
$store_path = 'aboutus';
$profileimage = $request->profileimage->store($store_path,'public');
$oldimage = $about->profileimage;
$file_address = $store_path.'/'.$request->profileimage->hashName();
\Storage::disk('public')->delete($oldimage);
$data['profileimage'] = $file_address;
}
Store image using original name
if($request->hasFile('profileimage')){
$store_path = 'aboutus';
$profileimage = $request->profileimage->storeAs($store_path, $uploadedFile->getClientOriginalName(),'public');
$oldimage = $about->profileimage;
$file_address = $store_path.'/'.$request->profileimage->getClientOriginalName();
\Storage::disk('public')->delete($oldimage);
$data['profileimage'] = $file_address;
}
Delete the old image while updating
public function update(Request $request, $id)
{
// other updates
if ($request->hasFile('image')) {
//delete old image if exist
if (File::exists(public_path($oldImage))) {
File::delete(public_path(oldImage));
}
//new image process
}
}

secured file in storage laravel

i am uploading file in storage like this :
/storage/uploads/contract/19/12199/document.pdf
now i need to to allow only authenticated user to see those document , i use this route :
Route::get('/storage/{pathToFile}', function($pathToFile) {
if (auth()->user()) {
return response()->file($pathToFile);
} else {
return 'Nope, sorry bro, access denied!';
}
});
this didn't work , still all files can be acceded even if user not logged in .
any idea ?
thanks
Did you symlink the public folder to storage folder? If so it would still be accessible because default public entrypoint would be "public" folder so "[host]/storage" would be available in that folder.
What I did in the past was use S3 driver and set file visibility to private then use:
public function get($path, $image)
{
$file = Storage::disk('s3')->get("private/images/". $path. "/" . $image);
return response($file, 200)->header('Content-Type', 'image/png');
}
In your case this would be changed to:
if (auth()->user()) {
$file = Storage::disk('s3')->get($pathToFile);
return response()->file($file);
} else {
return 'Nope, sorry bro, access denied!';
}
Note: S3 driver supports multiple storage solutions: https://flysystem.thephpleague.com/v1/docs/adapter/aws-s3-v2/

Zipping and downloading Amazon S3 bucket files and folders in Laravel

Is there a way to zip and download files and folders which are in Amazon S3 bucket, together in Laravel? I Want to zip the three folders and one file in the picture together and download it
Here's a half baked solution in a route file. Hope it helps.
https://flysystem.thephpleague.com/docs/adapter/zip-archive/
composer require league/flysystem-ziparchive
I put this in routes/web.php just to play with.
<?php
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use League\Flysystem\ZipArchive\ZipArchiveAdapter;
Route::get('zip', function(){
// see laravel's config/filesystem.php for the source disk
$source_disk = 's3';
$source_path = '';
$file_names = Storage::disk($source_disk)->files($source_path);
$zip = new Filesystem(new ZipArchiveAdapter(public_path('archive.zip')));
foreach($file_names as $file_name){
$file_content = Storage::disk($source_disk)->get($file_name);
$zip->put($file_name, $file_content);
}
$zip->getAdapter()->getArchive()->close();
return redirect('archive.zip');
});
You'll definitely want to do something different than just plopping it in the public dir. Maybe stream it out straight out as a download or save it somewhere better. Feel free to post comment/questions and we can discuss.
I did it the following way after looking at some solutions by streaming the zip directly to the client by using https://github.com/maennchen/ZipStream-PHP :
if ($uploads) {
return response()->streamDownload(function() use ($uploads) {
$opt = new ArchiveOptions();
$opt->setContentType('application/octet-stream');
$zip = new ZipStream("uploads.zip", $opt);
foreach ($uploads as $upload) {
try {
$file = Storage::readStream($upload->path);
$zip->addFileFromStream($upload->filename, $file);
}
catch (Exception $e) {
\Log::error("unable to read the file at storage path: $upload->path and output to zip stream. Exception is " . $e->getMessage());
}
}
$zip->finish();
}, 'uploads.zip');
}

Files not uploading due to unkown error using laravel

Laravel Version: 5.5
I have a problem when uploading a file. I have multiple files in the array, I am uploading these files two times in the same function for the first time I am checking pdf file version, and file dimensions this block of code works perfectly but in the second block of code I am again uploading these files for merging these files it gives me this error "The file "A4.pdf" was not uploaded due to an unknown error". When I remove the first block of code then the second block of code start working.I don't know where I did mistake, I have searched a lot but not found the answer.
This block of code checking pdf file version and dimensions.
$paper_size = array();
$del_files = array();
foreach ($files as $file) {
$filename = time().date('m-d-y').$file->getClientOriginalName();
$file->move(public_path().'/uploads/check_pdf_files/', $filename);
$version = $this->pdfVersion(public_path().'/uploads/check_pdf_files/'.$filename);
if($version > 1.5)
{
File::delete('public/uploads/check_pdf_files/'.$filename);
return Response::json(" Your PDF file version is greater than 1.4 which is not compatible with our system, Please make it lower version.", 400);
}
$get_paper_size = $this->get_pdf_dimensions('public/uploads/check_pdf_files/'.$filename);
$paper_size[] = $get_paper_size;
$del_files[] = $filename;
}
if(round($paper_size[0]['width']) != round($paper_size[1]['width']))
{
foreach ($del_files as $del)
{
File::delete('public/uploads/check_pdf_files/'.$del);
}
return Response::json(" Your Files dimensions is not matching please try with same dimensions.", 400);
}
This block of code using for merging the files.
$new_pdf_file = array();
foreach ($request->file as $merge_file)
{
$newFile_name = time().$merge_file->getClientOriginalName();
$merge_file->move('public/uploads/', $newFile_name);
$new_pdf_file[] = $newFile_name;
}
dd($new_pdf_file);
$pdf = new \LynX39\LaraPdfMerger\PdfManage;
foreach($new_pdf_file as $new)
{
$pdf->addPDF('public/uploads/dummy_uploads/'.$new, 'all');
}
$temp_name = time().$request->merge_name;
$pdf->merge('file',base_path(). '/public/uploads/' . Auth::user()->email . '/'.$temp_name.'.pdf', 'P');
foreach($new_pdf_file as $delete_new)
{
File::delete('public/uploads/dummy_uploads/'.$delete_new);
}
$user = DB::table('user_pdf_files')->insert([
'user_files' => $request->merge_name.'.pdf',
'filename' => $temp_name.'.pdf',
'type' => $request->type[0],
'user_id' => Auth::user()->id,
]);
Session::flash('success', 'Files Merged Successfully');
return Response::json('success', 200);`
You need the fully qualified path to where you want the files saved to. Anytime you are moving or copying a file, ensure that you are using public_path() with the relative path as a parameter. This function outputs the fully qualified path to the public folder. For example:
$merge_file->move(public_path('uploads'), $newFile_name);
This should be why the first code block is working vs. the second one. Not a very descriptive error, though!

Resources