Rename images in database to md5 but keep extensions - php

As the title says I'm wanting to change the image names stored in a database to md5 but keep the image extension, I had a go with the code below but it failed (probably due to the fact I haven't a clue what I'm doing) ...any ideas on how I could achieve my goal?
function get_file_extension($file_name) {
return substr(strrchr($file_name,'.'),1);
}
$query = "SELECT img FROM post";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)) {
$name = substr($row['img'], -4, 4);
$ext = get_file_extension($row['img']);
$notmd5 = $row['img'];
$md5img = md5($name).'.'.$ext;
$q = "UPDATE post SET img='$md5img' WHERE img='{$notmd5}'";
$r = mysql_query($q) or die(mysql_error());
}
..........................................................
Update
Answer:
Rename files in dir/folder and db names at same time:
function get_file_extension($file_name) {
return substr(strrchr($file_name,'.'),1);
}
//path to directory to scan
$directory = "thumbs/";
$directory2 = "md5/";
//get all image files with a .jpg extension.
$images = glob($directory . "*.*");
//print each file name
foreach($images as $image)
{
$imag = str_replace($directory, '', $image);
$ex = get_file_extension($imag);
$new = md5($imag).'.'.$ex;
rename($image, $directory2.$new);
$q = "UPDATE post SET img='$new' WHERE img='{$imag}'";
$r = mysql_query($q) or die(mysql_error());
}
When I originally asked my question I had already renamed the images in dir/folder but I had a backup of them so mixed the to jobs together and got my goal :)

First off, I'd recommend a batch update like this just be done with pure SQL, especially if the business logic is as simple as this, it can all be done natively in MySQL for sure.
Anyway.., one thing that pops out is the substr call to get the $name of the file, it's hardcoded to get only 4 characters and it's actually getting the extension not the name.
Try this instead:
$ext = get_file_extension($row['img']); // get ext first
// use length of $row['img'] - length of file extension to extract name
substr($row['img'], 0, strlen($row['img']) - strlen($ext) - 1);

Just do it in pure SQL:
UPDATE post SET img = CONCAT_WS('.',
MD5(TRIM(TRAILING CONCAT('.', SUBSTRING_INDEX(img, '.', -1)) FROM img)),
SUBSTRING_INDEX(img, '.', -1)
)

Related

Rename folder which contains special characters using PHP

I have the following names in my database and also in directories.
Zúñnga
Mariè
etc...
The problem is I tried to do this:
$oldname = '/home/website/public_html/profile/Zúñnga';
$newname = '/home/website/public_html/profile/Zuunga';
rename($oldname, $newname)
And it doesn't work...
The names are stored in a database.
This is the following script I've been using to get the names out of the database, convert them to UTF-8, but simply the rename function doesn't work...
...
foreach($query as $item)
{
$name_tags = utf8_encode($item['name_tags']);
$oldname = '/home/website/public_html/profile/'.$name_tags.'';
$text = iconv('UTF-8','ASCII//TRANSLIT', $name_tags);
$text_1 = preg_replace(array('/\s{2,}/', '/[\t\n]/'), ' ', $text);
$text_2 = preg_replace("/[^A-Za-z0-9- ]/", '', $text_1);
$name_tags_updated = str_replace(" ", "-", $text_2);
$newname = '/home/website/public_html/profile/'.$name_tags_updated.'';
rename($oldname, $newname)
$sql = 'UPDATE posts SET name_tags = "'.$name_tags_updated.'" where id = "'.$item['id'].'";
...
}
The query part is working fine; it's replacing the name with the good letters in the database, but when it comes to renaming the directory it simply doesn't work. Instead of changing the name to it's actual file, it just doesn't. I've tried to verify it this way
if(rename($oldname, $newname))
echo 'success';
else
echo 'fail';
it returns fail
On my website sometimes they are returned like this:
Mari�

Set a limit in the results (no mysql)

Can I put a limit to show in a list of images extracted from a folder? I should point out that I do not mean with mysql but simple php.
Practically from a folder I extract all the images, here, I would like to set a limit. is it possible? or must necessarily the database?
You mention "extracted from a folder" and also "or must necessarily the database" so I'm not sure what your source is.
If you are getting the list of images them from a folder, presumably using something like glob() or readdir() or scandir() then you end up with an array. If you only want to display a certain number of those images then simply stop after that number of iterations...
$imgs = glob('*.jpg');
$count = 0;
foreach ($imgs as $img) {
if ($count++ > 20) break; // place a limit of 20
echo "<img src='$img' alt='$img' />\n";
}
If you are using a database to obtain your list of image filenames then you would do something similar, controlling it within your loop:
$sql = "SELECT filename, alt_text FROM ...";
$conx = mysqli_connect($host, $user, $pass, $dbname, ...);
$results = mysqli_query($conx, $sql);
$count = 0;
while ($row = mysqli_fetch_assoc($conx, $results)) {
if ($count++ > 20) break; // place a limit of 20
echo "<img src='$row[filename]' alt='$row[alt_text]' />\n";
}
mysqli_free_results($results);
If I have not yet answered your question then please clarify. If I have, please vote for the answer.
Thanks!
Try
array_slice(scandir($dir), 0, $limit);

check all extensions in DB

I have a database with a column named "document_name". In that column are thousands of rows with document names, like:
kfhidfs.doc
kjfdjdf.png
dsdiusd.exe
etc.
etc.
I want to know which extensions my users uploaded in the past.
So, I select all rows:
$sql = "SELECT document_name FROM docs";
$query = mysql_query($sql);
while($fetch_doc = mysql_fetch_assoc($query)) {
And I know that I can split the name and the extension using EXPLODE, like:
// Example 1
$doc = $fetch_doc['document_name'];
$piece = explode(".", $doc);
echo $piece[0]; // document name
echo $piece[1]; // extension
But I only want to see each extension max. 1 time, as I want know which extensions are in the DB, I don't want to know how many.
But how can I arrange that?
Add them to an array, only if they're not already there:
$extensions = array();
while($fetch_doc = mysql_fetch_assoc($query)) {
$doc = $fetch_doc['document_name'];
$piece = explode(".", $doc);
$extension = $piece[1];
if (!in_array($extension, $extensions) {
$extensions[] = $extension;
}
}
// Here $extensions is an array of the different extensions, each present only once
You can use SQL to achieve that, what is most likely more powerful than PHP.
Use SUBSTRING_INDEX and GROUP BY:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(document_name,',',-2),',',1) AS extension
FROM docs
GROUP BY extension
This assumes there is only one .before the file extension
You can use that query with PHP like this:
$sql = "SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(document_name,',',-2),',',1) AS extension FROM docs GROUP BY extension";
$query = mysql_query($sql);
while($extension = mysql_fetch_assoc($query)) {
var_dump($extension);
}
BTW:
The original mysql extension is deprecated as of PHP 5.5.0, and is not recommended for writing new code as it will be removed in the future. Instead, either the mysqli or PDO_MySQL extension should be used. See also the MySQL API Overview for further help while choosing a MySQL API.
http://php.net/manual/en/intro.mysql.php
You could do something like this:
$extensions = array();
while($fetch_doc = mysql_fetch_assoc($query)) {
$doc = $fetch_doc['document_name'];
$piece = explode(".", $doc);
$extensions[$piece[1]] = true;
}
foreach($extensions AS $key=>$value) {
echo $key . "<br />";
}
In this way you add every extension to an array (a key can only exist once, so you will automatically have each extension only once). You will echo the contents of the array thereafter.

Delete files that are not in my database

I'm trying to delete photos from a folder, which is called, "photos", that are NOT currently in my database. (These are all photos that have stacked up as I've been building the website and testing it and such, so now it's time to take the site live and I don't want all this waste in it)
I have three tables with photo information in them, and a number of columns throughout. Below is a mockup query of about what I THINK it should look like.
SELECT left_image, right_image, photo1, photo2, photo3, photo4, home_photo
FROM about_photos, facilities, home
left_image and right_image go with about_photos.
photo1, photo2, photo3 and photo4 go with facilities.
home_photo goes with home.
Also, I need to use a wildcard for the end of the photo, because the files have thumbnails, so for instance the original photo would be called, abcimage.jpg but there would be abcimage.jpg, abcimage_medium.jpg, abcimage_thumb.jpg also in the database I only store, photos/abcimage and add the rest of the filename depending on where it goes.
$directory = "../path/to/photos_directory/";
//get all image files with a .jpg extension.
$images = glob($directory . "*.jpg");
foreach($images as $image)
{
$name = explode('_',$image);
$name = 'photos/' . $name[0];
$sql = mysql_query("SELECT id FROM table WHERE photo1='$name' OR photo2='$name'");
if(mysql_num_rows($sql) == 0)
unlink($directory . $image);
}
You have two options:
One:
With an SQL query, get a complete list of all the photos referenced in your database
iterate through the files in your directory
if the file is an image AND it is not in your list, delete the file.
Two:
iterate through the files in your directory
if the file is an image
query the database for that filename
if the response is empty, delete the file
The exact SQL query depends on your table structure, which you have not provided.
The best option depends mostly on scale. If there are lots of images in the database, then the first option involves having a very large list in memory. However the second version involves many more database queries. So it's a tradeoff.
There are more sophisticated options involving caching and pre-emptive queries, but I imagine you don't want to go that deep yet.
Something like the following. I've also got original files in the folder and I limit to 500 deletions at a time. Tweak as you need. Hope it saves somebody time...
<?php
require 'session.php';
require 'settings.php';
/* Execute the query. */
$DBH = new PDO($mssql_driver.'='.$mssql_server.';'.$mssql_dbkey.'='.$mssql_database, $mssql_username, $mssql_password);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$tsql = 'select * from ProductImage';
$PRE = $DBH->prepare($tsql);
$PRE->execute();
$pictures =$PRE->fetchAll(PDO::FETCH_ASSOC);
$directory = $_SERVER["DOCUMENT_ROOT"]."\..\..\products\pictures/";
//get all image files with a .jpg extension.
$images = glob($directory . "*.jpg");
$counter =0;
foreach($images as $image)
{
$name = explode('pictures/',$image);
$name = $name[1];
$foundImage = false;
print "checking: ".$name;
foreach ($pictures as $picture){
$original_file = explode('.', $picture['Image_Big']);
$original_file = $original_file[0].'-original.'.$original_file[1];
if ( ($picture['Image_Small'] == $name)|| ($picture['Image_Big'] == $name) || ( $original_file == $name) || ($picture['Image_Thumb'] == $name) || ($picture['Image_PriceList'] == $name)){
$foundImage = true;
break;
}
}
if (!$foundImage) {
unlink($directory . $name);
print "....deleting";
$counter += 1;
}
print "<br />";
if ($counter> 500){
exit;
}
}
?>

foreach() not "for eaching" items in array PHP

if I do this, it works:
$data_array2 = mysql_query("SELECT pic_loc FROM pictures WHERE user_id = '".$id."'");
$cell_pictures = mysql_fetch_array($data_array2);
foreach($cell_pictures as $pics_being_deleted)
{
unlink($pics_being_deleted);
}
Problem being is that the above code is nested meaning it runs a new MySQL query for each time it runs the unlink function so I made the below code to make it not do that:
$the_pics_raw_2 = array();
$data_array2 = mysql_query("SELECT pic_loc FROM pictures WHERE user_id = '".$id."'");
while($cell_pictures = mysql_fetch_array($data_array2))
{
$the_pics_raw = $cell_pictures['pic_loc'];
$the_pics_raw_2[] = $the_pics_raw;
}
$the_pics_raw_3 .= " \"../../". implode("\" , \"../../" ,$the_pics_raw_2)."\"";
$the_pics = array($the_pics_raw_3);
foreach($the_pics as $pics_being_deleted)
{
unlink($pics_being_deleted);
}
I get this error in return:
Warning: unlink( "../../users/biondizzle/photos/pic_3387677.png" , "../../users/biondizzle/photos/pic_1581185.png") [function.unlink]: No such file or directory
it's obviously not going to find the "../../users/biondizzle/photos/pic_3387677.png" , "../../users/biondizzle/photos/pic_1581185.png" directory because that's 2 separate directories running at the same time so the foreach() isn't "foreaching".
Any way to get the unlink() to run separately for each directory i have listed in the array, I thought I would get it to work by adding the commas and quotations with the implode()?
Thanks a bunch, hope I explained it well enough
-Mike
I think this is what you want to do:
while($cell_pictures = mysql_fetch_array($data_array2)) {
$the_pics_raw = $cell_pictures['pic_loc'];
$the_pics[] = "../../" . $the_pics_raw;
}
foreach($the_pics as $pics_being_deleted) {
unlink($pics_being_deleted);
}
You will notice I have removed the $the_pics_raw_3 .= " \"../../". implode("\" , \"../../" ,$the_pics_raw_2)."\""; line as it was converting the array into a string, which was making it impossible to then foreach over.
Use this code:
$the_pics_raw = array();
$data_array2 = mysql_query("SELECT pic_loc FROM pictures WHERE user_id = '".$id."'");
while($cell_pictures = mysql_fetch_array($data_array2))
{
array_push($the_pics_raw,"../../".$cell_pictures['pic_loc']);
}
foreach($the_pics as $the_pics_raw)
{
unlink($pics_being_deleted);
}

Categories