PHP : Updating new image still showing the old image - php

So I am creating a new folder everytime if folder not exists using mdkir.
$dir_name = '../../assets/contestant_double/'.$event_id.'eventPortfolio/';
if(!is_dir($dir_name)){
mkdir('../../assets/contestant_double/'.$event_id.'eventPortolfio/', 0777, true);
}
Now I am trying to update my uploaded image on that folder. And its working fine when i look on that designated directory
$static_name = $event_id."d".$getThed1d2."_contestant_";
$extension = pathinfo($name, PATHINFO_EXTENSION);
$theRealName = $static_name.$lastDigit.".".$extension;
echo $theRealName;
But when i try to get the image why is it still showing up the old image instead the new one?
<img class="img_here_edit" src="../assets/contestant_double/'.$event_id.'eventPortfolio/'.$soc_sql['images'].'" width="100%" >
I doubt but I'm not sure that its on my new created directory mdkir which has 0777 because those of my code are working fine in my other regular folder? How do i solve this

use unlink(''); function to old image it will solve your problem

Why not delete the old image and create and upload a new image with the same name?.

Try sending a random id at the end of image url to get the latest image like this :
<img class="img_here_edit" src="../assets/contestant_double/'.$event_id.'eventPortfolio/'.$soc_sql['images'].'?'.time().'" width="100%" >

what you see is the picture on browser cache, so you have to clear cache of browser. however, you wont do that every time you replace a picture either your users, it is too tedious and unpractical. I had same sutation and what i did was the follown. create filename + time().jpg like this.
So by the time i was going to replace old picture, i loaded from folder, delete it an then place new one. look...
function uploadphoto( $id, $ref ) {
$find = $ref.'_';
$data = $_POST[ 'image' ];
list( $type, $data ) = explode( ';', $data );
list( , $data ) = explode( ',', $data );
$data = base64_decode( $data );
$imageName = $ref.'_'.time().'.jpg'; // new picture name
foreach(glob('uploads/'.$find.'*.*') as $filename){
$localizacion = $_SERVER['DOCUMENT_ROOT'].'/'. $filename ;
chmod('./uploads', 0777);
unlink($localizacion);
}
file_put_contents( 'uploads/' . $imageName, $data );
}

Related

Prevent uploading file before form submit in richtext editors?

I am trying to prevent from uploading image before form submit using summernote editor.
The code I was using (jquery/ajax) worked well for uploading image, but it was uploading image instantly when I add it to editor.
This was not desired behavior for me, 'couse if user add image to editor and then decide to close tab/close browser or go to another address, image will be stored on server - so I would like to upload image only when submit button is clicked (until then, it should be there only as preview).
I use following code which is parsing base64 coded image from editor, decoding and uploading to server.
it works fine when adding new article or updating article without adding new image into it.
Example : if article has 2 old images allready, and I add 1 more image then its trying to reupload that old images again, but old images are decoded so it doesn't upload them and inserting an undefined link into the editor.
I tried to validate with the server using :
if(file_exists($filename)){
echo 'Already exist';
}
But had no luck to make it work.
Here is my code :
if(strpos($submitted_content, '<img') !== false && strpos($submitted_content, ';base64') !== false) {
$doc = new DOMDocument();
$doc->loadHTML($submitted_content);
$tags = $doc->getElementsByTagName('img');
foreach($tags as $tag) {
// Get base64 encoded string
$srcStr = $tag->getAttribute('src');
$base64EncData = substr($srcStr, ($pos = strpos($srcStr, 'base64,')) !== false ? $pos + 7 : 0);
$base64EncData = substr($base64EncData, 0, -1);
// Get an image file
$img = base64_decode($base64EncData);
// Get file type
$dataInfo = explode(";", $srcStr)[0];
$fileExt = str_replace('data:image/', '', $dataInfo);
// Create a new filename for the image
$newImageName = str_replace(".", "", uniqid("img_", true));
$filename = $newImageName . '.' . $fileExt;
$file = '../uploads/large/' . $filename;
// Save the image to disk
$success = file_put_contents($file, $img);
$imgUrl = 'http://localhost/haber/uploads/large/' . $filename;
// Update the forum thread text with an img tag for the new image
$newImgTag = '<img src="' . $imgUrl . '" />';
$tag->setAttribute('src', $imgUrl);
$tag->setAttribute('data-original-filename', $tag->getAttribute('data-filename'));
$tag->removeAttribute('data-filename');
$submitted_text = $doc->saveHTML(); //This is the result of the editor to add database
}
Any help will be appricated! Thanks.
Solution :
I just needed to add if statement under foreach and take $submitted_text = $doc->saveHTML(); out of foreach, it works like a charm now.
if(preg_match('/data:image/', $srcStr)){}
if you want to add images to database, you can collect $filename to array $arr = array(); and implode or foreach in to database.
Can be used for all editors.

Image Intervention w/ Laravel Storage

I'm using the storage facade to store an avatar which works fine, but I want to resize my image like I did in previous versions of Laravel.
How can I go about doing this?
Here is what I have so far (doesn't work)
$path = $request->file('createcommunityavatar');
$resize = Image::make($path)->fit(300);
$store = Storage::putFile('public/image', $resize);
$url = Storage::url($store);
Error Message:
Command (hashName) is not available for driver (Gd).
You're trying to pass into putFile wrong object. That method expects File object (not Image).
$path = $request->file('createcommunityavatar');
// returns \Intervention\Image\Image - OK
$resize = Image::make($path)->fit(300);
// expects 2nd arg - \Illuminate\Http\UploadedFile - ERROR, because Image does not have hashName method
$store = Storage::putFile('public/image', $resize);
$url = Storage::url($store);
Ok, now when we understand the main reason, let's fix the code
// returns Intervention\Image\Image
$resize = Image::make($path)->fit(300)->encode('jpg');
// calculate md5 hash of encoded image
$hash = md5($resize->__toString());
// use hash as a name
$path = "images/{$hash}.jpg";
// save it locally to ~/public/images/{$hash}.jpg
$resize->save(public_path($path));
// $url = "/images/{$hash}.jpg"
$url = "/" . $path;
Let's imagine that you want to use Storage facade:
// does not work - Storage::putFile('public/image', $resize);
// Storage::put($path, $contents, $visibility = null)
Storage::put('public/image/myUniqueFileNameHere.jpg', $resize->__toString());
The put method works with the Image intervention output.
The putFile method accepts either an Illuminate\Http\File or Illuminate\Http\UploadedFile instance.
$photo = Image::make($request->file('photo'))
->resize(400, null, function ($constraint) { $constraint->aspectRatio(); } )
->encode('jpg',80);
Storage::disk('public')->put( 'photo.jpg', $photo);
The above code resizes the uploaded file to 400px width while holding the aspect ratio. Then encodes to jpg at 80% quality.
The file is then stored to the public disc.
Note you must provide a filename, not just the directory.
Using Laravel 5.8
I had a similar issue when trying to read an image file with Image when this one was saved and loaded with Storage.
Beside all the answers I wasn't sure why it wasn't working.
Exception when Image was trying to read the file
Intervention\Image\Exception\NotReadableException : Unable to init from given binary data.
Short answer
Adding ->encode()solved the issue
http://image.intervention.io/api/encode
Scenario
Basically I had a test like this
Storage::fake();
$photo = factory(Photo::class)->create();
$file = \Image::make(
UploadedFile::fake()->image($photo->file_name, 300, 300)
);
Storage::disk($photo->disk)
->put(
$photo->fullPath(),
$file
);
And in the controller I had something like this
return \Image::make(
Storage::disk($photo->disk)
->get(
$photo->fullPath()
)
)->response();
Solution
After investigation I realized that any file created by Image and saved by the Storage had a size of 0 octets.
After looking at all the solutions from this post and few hours after, I noticed everyone was using encode() but no one did mention it was that. So I tried and it worked.
Investigating a bit more, Image does, in fact, encode under the hood before saving.
https://github.com/Intervention/image/blob/master/src/Intervention/Image/Image.php#L146
So, my solution was to simple doing this
$file = \Image::make(
\Illuminate\Http\UploadedFile::fake()->image('filename.jpg', 300, 300)
)->encode();
\Storage::put('photos/test.jpg', $file);
testable in Tinker, It will create a black image
The cleanest solution I could find—using the native Storage facade—is the following. I can confirm that this works in Laravel 5.7, using intervention/image version 2.4.2.
$file = $request->file('avatar');
$path = $file->hashName('public/avatars');
$image = Image::make($file)->fit(300);
Storage::put($path, (string) $image->encode());
$url = Storage::url($path);
I do it this way:
Resize and save image somewhere (such as in the public folder).
Create a new File and pass it to Laravel filesystem functions (such as putFileAs).
Delete temporary intervention file
Note: Of course you can modify it according to your needs.
$file = $request->file('portfolio_thumb_image');
$image = Image::make($file);
$image->resize(570, 326, function ($constraint) {
$constraint->aspectRatio();
});
$thumbnail_image_name = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME).'.'.$file->getClientOriginalExtension();
$image->save(public_path('images/'.$thumbnail_image_name));
$saved_image_uri = $image->dirname.'/'.$image->basename;
//Now use laravel filesystem.
$uploaded_thumbnail_image = Storage::putFileAs('public/thumbnails/'.$portfolio_returned->id, new File($saved_image_uri), $thumbnail_image_name);
//Now delete temporary intervention image as we have moved it to Storage folder with Laravel filesystem.
$image->destroy();
unlink($saved_image_uri);
Make sure to add use Illuminate\Http\File; to top of your file for this to work, and read through the documentation section Automatic Streaming.
This assumes you want all jpegs
$path = $request->file('createcommunityavatar');
$resize = Image::make($path)->fit(300)->encode('jpg');
$filePath = $resize->getRealPath() . '.jpg';
$resize->save($filePath);
$store = Storage::putFile('public/image', new File($resize));
$url = Storage::url($store);
This is how I am doing it in my application with comments to help
// Get the file from the request
$requestImage = request()->file('image');
// Get the filepath of the request file (.tmp) and append .jpg
$requestImagePath = $requestImage->getRealPath() . '.jpg';
// Modify the image using intervention
$interventionImage = Image::make($requestImage)->resize(125, 125)->encode('jpg');
// Save the intervention image over the request image
$interventionImage->save($requestImagePath);
// Send the image to file storage
$url = Storage::putFileAs('photos', new File($requestImagePath), 'thumbnail.jpg');
return response()->json(['url' => $url]);
I've done it with following way, its simple and without any path confusion :
//Get file
$path= $request->file('createcommunityavatar');
// Resize and encode to required type
$img = Image::make($file)->fit(300)->encode('jpg');
//Provide own name
$name = time() . '.jpg';
//Put file with own name
Storage::put($name, $img);
//Move file to your location
Storage::move($name, 'public/image/' . $name);
Try updating the GD extension for the current php version.
If that doesn't help, try saving the resized image on local disk and using Storage::putFile.
You may delete the file once it has been uploaded to your storage path.
The second parameter to your putFile method is an instance of the Image Intervention class. You need to pass this as the second parameter to the putFile method.
$resize->save($absolutePath . 'small/' . $imageName);
You can't store an \Intervention\Image\Image object directly with the Laravel 5 filesystem. What you can do is resize the image from your request, and save it under the same tmp path. Then just store the uploaded (overwritten) file to the filesystem.
Code:
$image = $request->file('createcommunityavatar');
//resize and save under same tmp path
$resize = Image::make($image)->fit(300)->save();
// store in the filesystem with a generated filename
$store = $image->store('image', 'public');
// get url from storage
$url = Storage::url($store);
In my case the error was caused by calling the hashName method on an image instance.
//initially
$image = Image::make(request('image')->getRealPath());
$filename = $image->hashName();
//to fix the error
$image = Image::make(request('image')->getRealPath());
$filename = request('image')->hashName();

Move file to directory

So with your help I have been able to assemble the below.
$dir = "./reporting/live-metrics/";
$des = "./reporting/historic-metrics/";
$ctime = time();
foreach (glob($dir."*") as $file) {
$live = file_get_contents($file);
if (strpos($live, 'CORO') === false && filemtime($file) < time() - 1 * 10) {
$exclude[] = $live;
$lines = file( $file , FILE_IGNORE_NEW_LINES );
$lines[3] = 'Taken Down';
$lines[5] = $ctime;
file_put_contents( $file , implode( "\n", $lines ) );
if (!file_exists($des.basename($file).PHP_EOL)) {
mkdir($des.basename($file), 0777, true);
}
rename($file,$des.$ctime);
}
}
My issue is that I am attempting to move the file to the new directory created but I am having a little issue with it. No matter what I do I can only get it to move to $des, i cant seem to get ti to move to the dynamicaly created directory for each specific file. I am assuming it has to do with the fact I am not using rename to its correct params. Below are the some of the combinations I have tried to get it to rename and move.
rename($file,$des.basename($file).PHP_EOL.$ctime); //doesn't move or rename
rename($file,$des.basename($file).$ctime); //adds to historic-metrics/ as jason1465519298
I also tried creating a function and setting the rename to call on that. eg.
$path = $des.basename($file).PHP_EOL;
rename($file,$path.$ctime);
Currently the script is great up until the moving the file. It will move it to ./reporting/historic-metrics/ but I would like it to move to the directory just created. EG, if the file it is currently handeling is called 'Jason' then it will create ./reporting/historic-metrics/Jason but move the file to ./reporting/historic-metrics/
There seems to be two possibilities:
Source or destination file paths may be wrong, you can print and check
The newly created destination directory is getting the
correct permission & ownership.
Otherwise your script looks OK.
I finally got it. My main issue was trying to get the filepath to send the file to. After a few interruptions and rethinking my approach I came up with the below. I know it isn't pretty or as slim as could be made but it does the job perfectly.
$dir = "./reporting/live-metrics/";
$des = "./reporting/historic-metrics/";
$ctime = time();
foreach (glob($dir."*") as $file) {
$live = file_get_contents($file);
if (strpos($live, 'CORO') === false && filemtime($file) < time() - 1 * 10) {
$exclude[] = $live;
$lines = file( $file , FILE_IGNORE_NEW_LINES );
$lines[3] = 'Taken Down';
$lines[5] = $ctime;
file_put_contents( $file , implode( "\n", $lines ) );
if (!file_exists($des.basename($file).PHP_EOL)) {
mkdir($des.basename($file), 0777, true);
}
$user = basename($file); //Gets file name that was used in mkdir
$path = (String) $des.$user."/"; //Compiles variables into string
rename($file,$path.$ctime);
}
}

preg_replace_callback returns empty

First of all, I should say that this is a WordPress based question, which I originally asked on the WordPress StackExchange, here. But I think it's turned into a more PHP-based question so that's why I'm asking here.
So basically, I've written this preg_replace_callback function, which, on saving/publishing the post, will replace all of the image URLs with URLs from the WP Uploads directory. I've had fleeting success with this; sometimes it works, but only on one of the URLs (in my test examples on my site I have 3 img tags, each split up with paragraphs.
Here is my code:
add_filter('content_save_pre', 'getpostimgs'); // content_save_pre filter may be depreceated? => http://adambrown.info/p/wp_hooks/hook/content_save_pre
function getpostimgs() {
global $post;
$postContent = $post->post_content;
$content = preg_replace_callback(
'/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', // pattern to match to (i.e the contents of an <img src="..." /> tag)
function ($match) {
$imgURL = $match[1]; // the second array (#1) (0-based) is the array with the URLs in. First array (#0) has the whole img tag in.
$image_data = file_get_contents($imgURL); // Get image data
$filename = basename($imgURL) . "-" . $post->ID . ".jpg"; // Create image file name
if( wp_mkdir_p( $upload_dir['path'] ) ) { // check upload file exists and the permissions on it are correct
$file = $upload_dir['path'] . '/' . $filename;
} else {
$file = $upload_dir['basedir'] . '/' . $filename;
} // save file to server
file_put_contents( $file, $image_data ); // save the file to the server
return $file;
},
$postContent
);
return $content;
}
I've added some comments along the way to hopefully explain what I'm doing at each stage. I'm not a PHP wizard (I mainly do WordPress PHP) so be nice! Also, as I put in the comments, the WordPress filter I'm using, content_save_pre, which is supposed to edit the content before being saved to the database, has been depreciated. But that's a WordPress issue, so I'll consult the guys on the WordPress Stackexchange about that one.
Anyway, my main problem is that when I hit save, the content is completely wiped. As I said above, I've had fleeting success - sometimes it will replace maybe one of the URLs, other times it won't, and most of the time it simply wipes all the content. I'm assuming there's something wrong with the preg_replace_callback.
Lastly: as you may have seen from the link I posted to the Wordpress StackExchange (right at the top), I originally coded this up by using a preg_match_all to find all the image URLs, then used a foreach loop to go through the array of URLs and had a prey_replace to replace the URLs. That code is here if you want to take a look at that. I changed it based on the advice on this thread (correct answer). But both methods act pretty much the same.
Thanks for any help :)
EDIT: I've updated my code a little, made a few silly mistakes regarding global variables/variable scope and a few syntax/WP errors. Here's my updated code:
function getpostimgs() {
global $post;
$postContent = $post->post_content;
$content = preg_replace_callback(
'/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', // pattern to match to (i.e the contents of an <img src="..." /> tag)
function ($match) {
global $post, $postContent;
$upload_dir = wp_upload_dir(); // Set upload folder
$imgURL = $match[1];
$image_data = file_get_contents($imgURL); // Get image data
$filename = basename($imgURL) . "-" . $post->ID . ".jpg"; // Create image file name
if( wp_mkdir_p( $upload_dir['path'] ) ) { // check upload file exists and the permissions on it are correct
$file = $upload_dir['path'] . '/' . $filename;
} else {
$file = $upload_dir['basedir'] . '/' . $filename;
} // save file to server
file_put_contents( $file, $image_data ); // save the file to the server
return $file;
},
$postContent
);
return $content;
}
add_filter('content_save_pre', 'getpostimgs'); // content_save_pre filter may be depreceated? => http://adambrown.info/p/wp_hooks/hook/content_save_pre
If I call this function on a single.php page or something, it will work, i.e. the Original Image URLs in the post content which is returned have been replaced by Upload Directory URLs, so the regex and stuff is correct. However, it doesn't work when I try to publish/update a post (the content is usually wiped). Any ideas?

Zend_Form_Element_File the move_uploaded_file function don't return anything

I am trying to upload a picture. I have Form_Zend and I use:
$image = new Zend_Form_Element_File('image');
$image->setLabel('Upload an avatar:')
->setMaxFileSize(8388608)
// ->setDestination('./usersImages')
->setDescription('Click Browse and choose an image');
$image->addValidator('Count', false, 1);
$image->addValidator('Size', false, 8388608);
$image->addValidator('Extension', false, 'jpg,jpeg,png,gif');
$this->addElement($image, 'image');
My controller action code:
if ($form->image->isUploaded()) {
$values = $form->getValues();
$source = $form->image->getFileName();
$extention = substr($source, strrpos($source, '.', -1));
$date = date('mdYhisa', time());
$new_image_name = 'avatar_' . $date . '_' . $idUser . $extention;
$destination = "C:\\xampp\\tmp\\Srututututut.png";
$image_saved = move_uploaded_file($source, $destination);
if ($image_saved) {
$data = array(
'img' => $new_image_name,
);
$userDT->update($data, 'id=' . $idUser);
}
}
}
But this move_uploaded_file is not returning nothing :/
What I have done:
Checked if the file is uploading - yes it is in: C:\xampp\htdocs\Story\public\usersImages (if I set destination in this form element) or
C:\xampp\tmp (if I dont set it)
I was wondering about access to this folders but if it save there this images I think it has rights but I set in the apache:
<Directory "C:/xampp/htdocs/Story/public/usersImages">
Allow from All
</Directory>
I was even tried use this function only in C:\xampp\tmp folder:
$source: C:\xampp\tmp\database.png
$destination: C:\xampp\tmp\Srututututut.png
And still nothing :/
Do You have any suggestions?
I think that the problem is with $source = $form->image->getFileName();. The reason is that it will return a name of the file uploaded rather than where it was uploaded to (i.e. its temporary localization).
Thus, I think your source should be as follows:
$fileInfo = $mainForm->image->getTransferAdapter()->getFileInfo();
$source = $fileInfo['image']['tmp_name'];
// to check if the source really points to the uploaded file.
var_dump(file_exists($source));
Ok,
I have no idea why this function is not working. I have changed my idea to set the $form->image destination first in the controller and then rename it and it is working.
Thanks for help guys ;D

Categories