Laravel Backpack save image with original name - laravel

I am using laravel backpack for my backoffice and i need to upload some images, i copy the code from their website and works fine, but i need the original name on the images, i tried some things, but is not working.
What i need to change here?
public function setImageAttribute($value)
{
$attribute_name = "image1";
$disk = "uploads"; // or use your own disk, defined in config/filesystems.php
$destination_path = "productimg"; // 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
$image1 = \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, $image1->stream());
// 3. Delete the previous image, if there was one.
\Storage::disk($disk)->delete($this->{$attribute_name});
// 4. 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('uploads/', '', $destination_path);
$this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
}
}

As far as I know, Backpack gets the content of the image file base 64 encoded. So the original file information is discarded.
If you need it, you should use the upload field type (but you won't see the image preview) or create your own field type modifying the original (/vendor/backpack/pro/resources/views/fields/image.blade.php).
For example you can create a support <input type="hidden" name="{{ $field['name'] }}__filename"> where you store the file name via JS.

you need to replace this
$filename = md5($value.time()).'.jpg';
with this
$filename = $value->getClientOriginalName();
but you have to be sure that all your images has an unique name or you must add a random prefix to file name to prevent duplacated names

Related

Replace Old image with new image in laravel

CONTROLLER
public function updateproduct(Request $request, $id)
{
// dd($request->all());
$request->validate([
'name'=>'required',
'description'=>'required',
'price'=>'required|numeric',
'quantity'=>'required|numeric',
]);
$product = Product::where('id', $id)->first();
if(is_null($product)) {
$product = new Product();
}
$product->name=$request->name;
$product->description=$request->description;
$product->price=$request->price;
$product->quantity=$request->quantity;
if($request->hasfile('images')){
$existingimages = Image::where(['product_id'=> $product->id, 'source'=> 1])->get();
if($existingimages->count() > 0)
foreach($existingimages as $existingimage) {
$filename = public_path().'files/'.$existingimage->name;
if(file_exists($filename)){
unlink($filename);
$existingimage->delete();
}
}
foreach($request->file('images') as $file){
$name = rand(1,9999).'.'.$file->getClientOriginalName().$file->getClientOriginalExtension();
if($file->move(public_path().'/files/', $name)){
$updateImage = Image::firstWhere('product_id', $product->id);
$updateImage->images = $name;
$updateImage->source = 1;
$updateImage->save();
}
}
}
Please check updated question. Request you to correct me if I wrong. Right now it only updates 1 image and other images remains same. please help me with this.
Your code is somewhat confusing, I'm afraid.
Your request appears to allow for multiple images to be uploaded. Here :
if(file_exists($imagePath)){
unlink($imagePath);
}
you look like you're trying to delete any images that already exist, but when you store upload images you're assigning them a random name (which Laravel can already handle for you, by the way, so there's no need to do it yourself) so you're unlikely to be actually deleting them because there'll likely be no file at that location anyway.
Nowhere does your code actually delete any existing images from the database. Essentially what you want to do is :
If the upload has images, retrieve all the existing images for that product.
Delete the physical files for those existing images.
Delete the database entries for those existing images.
Upload your new images and save their details to the database.
Translating that into code means :
if($request->hasfile('images')){
// Delete any existing image files and database entries.
$existingimages = Image::where('product_id', $product->id)->get();
if($existingimages->count() > 0)
foreach($existingimages as $existingimage) {
$filename = public_path().'files/'.$existingimage->name;
unlink($filename);
$existingimage->delete();
}
}
// Carry on with your upload
}
It adds new images because you are using the Image::create method. If I understood correctly, you want to modify the images of your products in the image table.
Try to modify your code like :
$updateImage = Image::firstWhere('product_id', $product->id);
$updateImage->images = $name;
$updateImage->source = 1;
$updateImage->save();

RuntimeException laravel 5.8 RuntimeException This driver does not support creating temporary URLs

RuntimeException This driver does not support creating temporary URLs.
I am trying to generating Temp Url for every request Laravel version 5.8 below code trying showing an error.
This driver does not support creating temporary URLs.
$url = "66.jpeg";
$url = Storage::disk('public')->url($url);
$url = Storage::disk('public')->temporaryUrl(
'66.jpeg', now()->addMinutes(5)
);
From my knowledge, temporaryUrl is a method used on a drivers such as s3 to create a temporary url for a privately stored asset.
If you would like to set a temporary url for a file, it may help to use Cache to temporarily store the path.
Cache can set a key/value for a set amount of time. A url can be create which links to an endpoint. Then endpoint can then be created which returns the contents of that file:
// Creating temp file index in cache
$image = '66.jpg';
Cache::put('/temp/' . $image, 300); // 5 minutes
Now in, for example, TempController.php (visiting http://example.com/temp/66.jpg):
public function show($image)
{
if (Cache::get('/temp/' . $image) && ! Storage::disk('public')->exists($image)) {
// not in cache or do not exist, maybe redirect...
};
return Storage::disk('public')->get($image);
}
This is a proof of concept however I hope this helps.

Adding watermark on image from databases in Laravel 5.3

I am trying to add watermark on image from database in Laravel using Intervention Image package. In my database table I am saving the path of the image. I am using Accessors in my model to get access to the field of the image path but I am getting this error:
Method insert does not exist.
Here is my model:
Here is my blade:
public function getFilePathAttribute($value){
$img = Image::make(public_path($value)); //your image I assume you have in public directory
$img->insert(public_path('watermark.png'), 'bottom-right', 10, 10); //insert watermark in (also from public_directory)
$img->save(public_path($value)); //save created image (will override old image)
return $value; //return value
}
It is better to do it on upload so you do it Once not always when trying to access the image path from DB (less proccess) FYI: this will save already watermarked image

Unlink, image into directory

I have a file called delete.php inside where I created this code:
// check if the 'id' variable is set in URL, and check that it is valid
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
// get id value
$id = #$_GET['id'];
$img = #$_GET['h_image'];
if(file_exists($img)){
unlink('../images/'.$img);
}
// delete the entry
$result = DB::table('questions')
->where('id', '=', $id)
->delete();
// redirect back to the view page
header("Location: index.php");
}
else
// if id isn't set, or isn't valid, redirect back to view page
{
header("Location: index.php");
}
The content is properly deleted from the database, but unfortunately I can not erase the image corresponding to the directory "images".
I tried with unlink, but by mistake.
How can I do?
Obviously the image must match the content to be deleted.
Thanks guys, I hope for your help.
I did so, but always from tabase but not delete the image from the directory:
Maybe I'm wrong path of the image? The GET?
// get id value
$id = #$_GET['id'];
$path = #$_GET['img'];
if(file_exists($path))
unlink("images/".$path);

Zend Image Upload validation issue edit page

I'm working on Zend Framework 1.11.12 version. In my add form where we've to put file upload (for photo upload) field and it has few validations as required, file extensions and size specific criteria mentioned as below, which is declared under my zend form:
// part of my form class (Default_Form_Photo::init)
$photo = new Zend_Form_Element_File('photo', '', array('required' => true));
$photo->setLabel('Photo')
->setDestination('/var/www/zendframework/public/uploads/');
// ensure its mandatory
#$photo->addValidator('required', true);
// ensure only one file
$photo->addValidator('Count', false, array('min' => 1));
// max 2MB
$photo->addValidator('Size', false, 2097152)
->setMaxFileSize(2097152);
// only JPEG, PNG, or GIF
$photo->addValidator('Extension', false, 'jpg,jpeg,png,gif');
$photo->setValueDisabled(true);
$this->addElement($photo, 'photo');
Now I have taken a hidden field, for edit page which will return me current image name, if no new image uploaded:
// hidden element for edit time photo save
$this->addElement('hidden', 'photo_uploaded', array( ));
I set this hidden element value from controller by $form->photo_uploaded->setValue($result['photo']).
Now the problem is: when user edit information, it does not allow saving because the file upload field is blank as no new image uploaded, but in my case have to use existing current image, which I am passing from hidden element to my controller.
So validation causes problem here, any idea how can i remove validation for my edit page where users do not have to upload new image every time, they are editing information.
Earliest response will be appreciated.
Thanks !
The answer to this requires you to add two functions to your form: isValid and getValues. First of all, remove required from the photo element as we are going to check for this in isValid:
/**
* Check if a photo has been submitted. If not, set the form element as required.
* #param $data Array of values
* #return Boolean true if all form element requirements are mets
*/
public function isValid($data)
{
//A photo has not been uploaded this time, nor previously.
if(!$data['photo'] AND !$data['photo_uploaded'])
{
$this->photo->isRequired(TRUE);
}
return parent::isValid($data);
}
/**
* Return an array of form element values
* #return Array of values
*/
public function getValues()
{
$values = $this->getValues();
//if photo has been uploaded, but no previous photos have been uploaded, then set photo_uploaded value.
if($values['photo'] AND !$values['photo_uploaded'])
{
$values['photo_uploaded'] = $values['photo'];
}
//if previous photo has been uploaded, but photo has not been uploaded this time, set photo value
if($values['photo_uploaded'] AND !$values['photo'])
{
$values['photo'] = $values['photo_uploaded'];
}
return $values;
}

Resources