PHP - Check for distinct filename on file upload - php

I'm pretty new to PHP. I hate to have to ask questions, because I'm sure this is documented somewhere, but after looking for a while, I just cannot seem to put two and two together.
I have a program that will allow multiple images to be uploaded to an item within the database. Basically, for each item in the database, there might be multiple image uploads.
Example:
Item: Xbox 360
Images:
Xbox360.jpg
side.jpg
front.jpg
The image and item information is all stored in the database (MySQL), but the images are stored within the filesystem, and the database points to the URL of the image(s) in the filesystem.
The problem I'm having is that everything works as expected, except it allows duplicate image names to be written to the database. It doesn't allow duplicate images to be written to the filesystem, which I'm happy with. I want to make sure that the name of an image is only added once to the database. If the image name is a duplicate to another, it needs to not write to the database.
add_db.php:
$uniqueDir = uniqid();
$directory = "img/$uniqueDir/";
db_addItem($id_category, $name, $cost, $description, $qty, $directory); //Adds to the `items` table
foreach ($_FILES['i_file']['name'] as $filename) {
if ($filename != '' && $filename != 'No file chosen') {
//I think above is where I check for unique image names
$url = "img/$uniqueDir/$filename";
db_addImg($url, $filename); //Adds to the `img` table
$item_picsID = get_item_PicsID($filename, $url);
$itemID = get_itemID($directory);
db_insertImg($itemID, $item_picsID);
}
}
addFilesystem($directory); //Writes image(s) to filesystem
function db_addImg($url, $filename) {
include 'mysql_login_pdo.php';
// Create the SQL query
$query = "INSERT INTO img (`name`, `url`) VALUES(:filename, :url)";
$stmt = $db->prepare($query);
$stmt->execute(array(
':filename' => $filename,
':url' => $url
));
}
function db_insertImg($itemID, $item_picsID) {
include 'mysql_login_pdo.php';
// Create the SQL query
$query = "INSERT INTO `item_pics` (`item_id`, `img_id`) VALUES(:itemID, :item_picsID)";
$stmt = $db->prepare($query);
$stmt->execute(array(
':itemID' => $itemID,
':item_picsID' => $item_picsID
));
$db = null;
return;
}
Everything works, except it will write duplicate image names to the database. I want the image names to be distinct. I also don't want to rename the images (if possible).

You can define an UNIQUE index on the name column in img table, and then use slightly modified INSERT statement in your db_addImg function:
function db_addImg($url, $filename) {
//...
$query = "INSERT INGORE INTO img (`name`, `url`) VALUES(:filename, :url)";
//...
}
It will quietly cancel any insert where the is a UNIQUE key collision, which will end up in distinct filenames across your img table.

I would use a filename based on the primary key from the img table as you're guaranteed it's unique.
Otherwise, you'll need to guess a unique filename with some type of hashing and then check the file system. All of which can be expensive operations.
Looks like you are using PDO, so the static method lastInsertId will get the last insert id (primary key).
For example:
// after your insert to img
$filename = 'img' . $db->lastInsertId() . $extension;
This will require changing the img table slightly. But you're better off storing meta data (file type, size, etc) in this table as opposed to the file location (as that can change).

I think better to use hash value of your url as the primary key. Be cause string searching is much slower as int.

Related

php - compare between the indexes of one array and the values of another array

I have a project in which I should upload multiple images to the web page with image removal option.
So it's obvious when I upload images using input with name of images and remove some uploaded images the removed images don't be removed from the input and when I submit the form all images are inserted into database even removed images ..
Now when ever I remove an image from web page I append a hidden input with name of deletedImg[] inside my form : this input will have the index of removed image (eg. first image removed then the input with name deletedImg[] will have the value of 0,second image removed then another input with name deletedImg[] will have the value of 1 .. and so on)
These values are the indexes of removed images and I want to ignore them when I upload the images when the form is submitted .. how can I achieve this?
if(isset($_POST['post']))
{
$deleted = $_POST['deletedImg']; //This is the array containing the deleted image indexes
foreach($_FILES['images']['name'] as $key=>$val)
{
$nameOfImage = basename($_FILES['images']['name'][$key]);
$avatarTempName = $_FILES['images']['tmp_name'][$key];
// List of allowed image extensions
$avatarAllowedExtension = array("jpeg", "jpg", "png", "gif");
// Get avatar extension
$avatarExtension = strtolower(end(explode('.', $nameOfImage)));
if(in_array($avatarExtension, $avatarAllowedExtension))
{
$postImage = rand(0, 10000000000) . '_' . $nameOfImage;
// Move image into Covers folder
move_uploaded_file($avatarTempName, "Uploads\Posts\\" . $postImage);
// Insert image into database
$stmt = $con->prepare("insert into postImages (ID , userId , postID , postImg) values (DEFAULT , :userId, (select max(ID)from post) , :postImg)");
$stmt-> execute(array(
'userId' => $_SESSION['ID'],
'postImg' => $postImage
));
}
}
}
To get the values of this array you can use this:
$deleted = array_values($_POST['deletedImg']);
You then can use in_array($val, $deleted) to check of one of the posted imagename exists in the deleted array.

Insert images (NSData) into BLOB fields

From iOS app to php script, I want to store a bench of images as BLOB types:
$profile_images = $_REQUEST['profile_images_array'];//get the array of images
//loop the images and store them one by one
foreach($profile_images as $image){
$sqlinsertimages = "insert into profile_images (id_client,image) Values ('".$id."',mysql_real_escape_string('".$image."'))";
$result = mysql_query($sqlinsertimages);
}
The insert would work fine if I eliminate the image field (which is BLOB type), so the issue is obviously with the saving BLOB types in the table.
How to store properly the images in PHP as BLOB?
PS: not willing to adopt the file system storage.
Ok, I guess that work finally, didn't knew that I had to save the image to the server before saving it to MySQL:
foreach($profile_images as $image){
//Get the file as a string before inserting it to table
$content = file_get_contents($image);
$content = mysql_real_escape_string($content);
$sqlinsertimages = "insert into profile_images (id_client,image) Values ('".$id."','".$content."')";
$result = mysql_query($sqlinsertimages);
}

Need input on a dynamic query output script

I have a homepage that has a bunch of images as links to other pages that has info about that image.
Image Name: $varExampleNAME
Damage: $varExampleDMG
Health: $varExampleHP
Mana: $varExampleMP
So the only info that will change on this page will be the variables.
What I want is to run one query script so that depending on the $fileName of the $currentPage
it grabs that row from the table if the $fileName matches a certain row name.
This is the script to find out what my fileName is:
//include database connection file
include_once 'connect_to_db.php';
$currentFile = $_SERVER["SCRIPT_NAME"];
$img = array_pop(explode("/", $currentFile));
$fileName$ = basename($img, ".php").PHP_EOL;
I'm having problems with the actual query script. Can anyone shed some light on how this will be done?
My table name is image_Name
Columns include id, name, damage, health, mana.
You should design your tables in order to fit your needs, in this case to retrieve a row based on a parameter.
If the name field of the table is consistent with the script filenames, you should do [using PDO]:
// Create a connection handler - provide your credentials
$dbh = new PDO('mysql:host=localhost;dbname=yourDbNane','username','password');
// Prepare the query with a placeholder
$dbh->prepare('SELECT * FROM image_Name WHERE name = ?');
// Fill the placeholder with the filename
$dbh->execute( array($fileName) );
// Fetch the result, you are done!
$img = $dbh->fetch();

Pair a random image with a random quote and assign that pair a unique url

I would like to pair a set of pictures with a list of quotes each pulled randomly from their lists and assign that pair a unique url. Much like the The Nietzsche Family Circus does.
I'm pretty sure he is using php to pull randomly for the two lists and creating th url with those the picture and quotes unique identifiers.
Is there anybody who could help me get started on replicating this concept? Thanks.
You could always use a database. If you create a table in the database with one column for the unique url identifying the pair, one column for an image url, and one column for the quote text you could then do something like the following:
$quoteArray = array(); //in reality this would be filled with your quotes
$imageArray = array(); //this would be filled with your image urls
$pairs = array();
while(count($quoteArray) > 0 && count($imageArray) > 0) {
$quoteIndex = rand(0, count($quoteArray) - 1); //get some random indexes
$imageIndex = rand(0, count($imageArray) - 1);
$pairs[] = array('quote' => $quoteArray[$quoteIndex], 'image' => $imageArray[$imageIndex]);
unset($quoteArray[$quoteIndex]); //keep us from using the same quote twice
unset($imageArray[$imageIndex]); //same goes for the images
}
//this assumes your table has an autoincremeting id field
$stmt = $connection->prepare("INSERT INTO awesomeTable (quote, image) VALUES( :quote , :image )");
//$connection is a PDO which you would have created earlier...look in the php manual for information on setting this up
foreach($pairs as $pair) {
$uniqueId = sha1($quote . $image);
$stmt->execute(array(':quote' => $pair['quote'], ':image' => $pair['image']));
}
Then, to get a random url out:
$result = $connection->query("SELECT * FROM awesomeTable ORDER BY RAND() LIMIT 1");
$record = $result->fetch();
//record will contain either an object (accessed by $row->url, $row->quote, etc) or an
//associative array (accessed by $row['url'], $row['quote'], etc) depending on how you
//set up the PDO
Your page that would serve these up (images.php) would simply take an id passed to it (which would be unique because it was being autoincremented) and query the database to get the row (and therefore the quote and image) associated with that id.

How do i store array of image names dynamically into the database using PHP

i am using the jQuery Plugin Uploadify to upload files, and i store the image name with path into the database with simple mysql query and then retrieve it.
my MySQL database table is using the following entities,
id int(20)
image_url varchar(255)
my image store procedure is such as, i first rename the file, give it a unique name and move it to the desired directory. and then store the image name with path into the database.
currently by using simple mysql INSERT statement i am storing a single file name.
now i want to upload the array of image names with path. or i want to store as much image as i want dynamically into the single table col image_url, for some reason i plan to store 4 or more images, i want all the four image to have one particular id number.
how do i do it?
thank you
Edit 2
I removed the previous scripts, here's a new one:
basically what i want to achieve is when inserting into the database i would like to store the image path with names as arrays. so that i could store as much images i want into a particular id, for example an id 1 will have 3 images, id 2 will have 5 images , id 3 will have 4 images and so on
Best way to do this is to add a separate entry for each image url. You can also use a single entry and store all the urls as an array, but since you're storing this in a database that isn't very useful. Storing each entry separately makes it a lot easier to access and update the data.
Also, make sure the "id" field in your table isn't a primary key / auto incrementing. Otherwise you won't be able to use the same id more than once. I fixed that here:
// array with your images
$images = array('url1','url2','url3');
// determine a new id
$sql = "SELECT MAX(id) FROM images";
$res = mysql_query($sql);
list($id) = mysql_fetch_row($res);
// highest current id, plus one
$id++;
// now create a values array to insert in the database
$values = array();
foreach ($images as $image) {
$values[] = "($id, '".mysql_real_escape_string($image)."')";
}
// comma-separate the values
$values = implode(',',$values);
// run the query
$sql = "INSERT INTO images (id, image_url) VALUES $values";
mysql_query($sql);
If you do want to store arrays, it's best to serialize the data and use unserialize when you retrieve it. Example:
$images = array(...);
$images = serialize($images);
$sql = "INSERT INTO images (image_url) VALUES ($images)";
To add images, you should then first retrieve the data, unserialize the array, update the array with the new images, serialize it again, update the database entry.
It's not normalized well at all, but you could do this:
<?php
// ... your code here ...
try {
$dbh = new PDO( 'mysql:dbname=' . $your_database_name . ';host=' . $your_database_host, $your_database_username, $your_database_password );
} catch ( PDOException $e ) {
throw new Exception( 'Database connection failed: ' . $e->getMessage() );
}
$stmt_insert = $dbh->prepare("INSERT INTO images('url_array') VALUES (:image_array_json)");
$stmt_insert->execute( array(':image_array_json', json_encode( $image_array )) );
// ... et cetera ...
?>
... and to retrieve the array (assuming you know the image_id):
<?php
// ... your code here ...
try {
$dbh = new PDO( 'mysql:dbname=' . $your_database_name . ';host=' . $your_database_host, $your_database_username, $your_database_password );
} catch ( PDOException $e ) {
throw new Exception( 'Database connection failed: ' . $e->getMessage() );
}
$stmt_retrieve = $dbh->prepare("SELECT url_array FROM images WHERE image_id=:image_id");
$stmt_retrieve->execute( array(':image_id', $image_id) );
$ret = $stmt_retrieve->fetch( PDO::FETCH_ASSOC );
$image_array = json_decode( $ret['url_array'] );
// ... et cetera ...
?>

Categories