Rename uploaded image in numeric sequence (i + 1) - php

I have a json post that uploads photos. It works just fine. I want to change the name of the uploaded file as it is uploaded. I know how to do that. I want to add a number to the end of the file name before the image type extension. I know how to do that. I want the number to increment by one for each new file when I upload multiple images at once. I cant do that :-( Here is what Im working with:
if (!file_exists($vendimagepath) ) {
mkdir($vendimagepath,0777,TRUE);
}
$valid_extensions = array('gif', 'png', 'jpeg', 'jpg');
$uploader = new FileUpload('uploadfile');
// Handle the upload
$result = $uploader->handleUpload($vendimagepath);
if (!$result) {
exit(json_encode(array('success' => false, 'msg' => $uploader->getErrorMsg())));
} else {
echo json_encode(array('success' => true));
$_SESSION['success']=true;
$path = $uploader->getFileName();
$vendimagepath= $vendimagepath.$path;
$result = $db -> query("INSERT into vendimages (vendregid, vendimagepath) VALUES ('$vendredig', '$path')");
$result = $db -> update("UPDATE registervendors SET images='1' WHERE regid = '$vendredig' AND username='$vendusername' ");
}
I inserted a variable under the if statement at the top $x=1; and then under the $uploader=new fileupload I added a while loop with $x++; and put that closing brace at the end of the script. It didnt work. It uploaded files but they all end up with the same number (1) . I know why. The script is called for each new file uploaded so $x=1 restarts each time and therefore $x++ is 1 each time.

Since you want to count across page loads, you should use your $_SESSION. Before the uploads start set:
$_SESSION['upload_index'] = 1;
Then do $_SESSION['upload_index']++ each time you get a new uploaded file.

Related

Remove Prestashop orphan images not stored in DB

I need to clean a shop running Prestashop, actually 1.7, since many years.
With this script I removed all the images in the DB not connected to any product.
But there are many files not listed in the DB. For example, actually I have 5 image sizes in settings, so new products shows 6 files in the folder (the 5 above and the imageID.jpg file) but some old product had up to 18 files. Many of these old products have been deleted but in the folder I still find all the other formats, like "2026-small-cart.jpg".
So I tried creating a script to loop in folders, check image files in it and verify if that id_image is stored in the DB.
If not, I can delete the file.
It works but obviously the loop is huge and it stops working as long as I change the starting path folder.
I've tried to reduce the DB queries storing some data (to delete all the images with the same id with a single DB query), but it still crashes as I change the starting path.
It only works with two nested loops (really few...).
Here is the code. Any idea for a better way to get the result?
Thanks!
$shop_root = $_SERVER['DOCUMENT_ROOT'].'/';
include('./config/config.inc.php');
include('./init.php');
$image_folder = 'img/p/';
$image_folder = 'img/p/2/0/3/2/'; // TEST, existing product
$image_folder = 'img/p/2/0/2/6/'; // TEST, product deleted from DB but files in folder
//$image_folder = 'img/p/2/0/2/'; // test, not working...
$scan_dir = $shop_root.$image_folder;
// will check only images...
global $imgExt;
$imgExt = array("jpg","png","gif","jpeg");
// to avoid multiple queries for the same image id...
global $lastID;
global $delMode;
echo "<h1>Examined folder: $image_folder</h1>\r\n";
function checkFile($scan_dir,$name) {
global $lastID;
global $delMode;
$path = $scan_dir.$name;
$ext = substr($name,strripos($name,".")+1);
// if is an image and file name starts with a number
if (in_array($ext,$imgExt) && (int)$name>0){
// avoid extra queries...
if ($lastID == (int)$name) {
$inDb = $lastID;
} else {
$inDb = (int)Db::getInstance()->getValue('SELECT id_product FROM '._DB_PREFIX_.'image WHERE id_image ='.((int) $name));
$lastID = (int)$name;
$delMode = $inDb;
}
// if haven't found an id_product in the DB for that id_image
if ($delMode<1){
echo "- $path has no related product in the DB I'll DELETE IT<br>\r\n";
//unlink($path);
}
}
}
function checkDir($scan_dir,$name2) {
echo "<h3>Elements found in the folder <i>$scan_dir$name2</i>:</h3>\r\n";
$files = array_values(array_diff(scandir($scan_dir.$name2.'/'), array('..', '.')));
foreach ($files as $key => $name) {
$path = $scan_dir.$name;
if (is_dir($path)) {
// new loop in the subfolder
checkDir($scan_dir,$name);
} else {
// is a file, I'll check if must be deleted
checkFile($scan_dir,$name);
}
}
}
checkDir($scan_dir,'');
I would create two files with lists of images.
The first file is the result of a query from your database of every image file referenced in your data.
mysql -BN -e "select distinct id_image from ${DB}.${DB_PREFIX}image" > all_image_ids
(set the shell variables for DB and DB_PREFIX first)
The second file is every image file currently in your directories. Include only files that start with a digit and have an image extension.
find img/p -name '[0-9]*.{jpg,png,gif,jpeg}' > all_image_files
For each filename, check if it's in the list of image ids. If not, then output the command to delete the file.
cat all_image_files | while read filename ; do
# strip the directory name and convert filename to an integer value
b=$(basename $filename)
image_id=$((${b/.*/}))
grep -q "^${image_id}$" all_image_ids || echo "rm ${filename}"
done > files_to_delete
Read the file files_to_delete to visually check that the list looks right. Then run that file as a shell script:
sh files_to_delete
Note I have not tested this solution, but it should give you something to experiment with.

Auto increment file names PHP/MySQL

I am fairly new to the php world and have been creating an inventory tracking system for one of my side businesses. Most of the basics are working, but I am having issues with my "upload pdf" function. Even though it works and uploads the pdf file to its target location, I cannot get the file name ($docid) to be an integer that auto increments every time there is a submission so that files never have the same name. Below is the code I have working:
$pdfPath = "/Documents/TEST/";
$maxSize = 102400000000;
$docid = TEST;
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['upload_pdf'])) {
if (is_uploaded_file($_FILES['filepdf']['tmp_name'])) {
if ($_FILES['filepdf']['type'] != "application/pdf") {
echo '<p>The file is not in PDF</p>';
} else if ($_FILES['filepdf']['size'] > $maxSize) {
echo '<p class="error">File is too big! Max size is =' . $maxSize . 'KB</p>';
} else {
$menuName = "Order_Receipt_".$docid.".pdf";
$result = move_uploaded_file($_FILES['filepdf']['tmp_name'], $pdfPath . $menuName);
if ($result == 1) {
echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL=http://localhost/website/enter_new_order_success.html">';
} else {
echo '<p class="error">Error</p>';
}
}
}
I know I need some sort of loop to auto increment that $docid variable but I cannot seem to figure it out. I have read up on the topic, but auto increment with the if statement is throwing me off. Any help would be greatly appreciated.
Cheers
Well, unless you store the entries to keep track in a database or similar you could check what entries you have in your upload folder and increment it by one.
The glob function is useful for that:
http://php.net/manual/en/function.glob.php
$myFiles = sort(glob('/Documents/TEST/*.pdf')); // returns an array of pdf files in the target folder. Using sort to sort the array e.g. file_1_.pdf,file_2_.pdf,file_3_.pdf, etc
//last element
$lastFile = end($myFiles); //returns the last file in the array
//get the number and increment it by one
$number = explode('_',$lastFile);
$newNumber = $number[1] + 1; //add this to the name of your uploaded php file.
$pdfUploadedFile= "Order_Receipt_".$newNumber."_.pdf";
As pointed out in the comments... I find it a better idea to name it with a timestamp generated string. And also don't forget the quotes around your strings.
$docid = TEST;
should be:
$docid = 'TEST';
Edit
Even better would be naming it in a formatted date I suppose.
$pdfUploadedFile= "Order_Receipt_".date("Y-m-d-H-i-s").".pdf"; // will output something like Order_receipt_2014-09-24-11-14-44.pdf

Error diplaying image in php

I have an error displaying images in php, my script used to work, and now it doesnt :(.
My Script is this:
$image_id = intval($_REQUEST['id']);
//Query database for our images data and grab it fromt the array returned
$result = mysql_query(sprintf("SELECT data, file_size, mime_type FROM _system_image WHERE id = %d;", $image_id));
$row = mysql_fetch_array($result);
//Set the headers so the browser knows an image is coming and then echo out the data
header("Content-type: " . $row['mime_type']);
header("Content-length: " . $row['file_size']);
echo $row['data'];
exit();
And my script for uploading photos is:
//Create an array of potential errors for uploading images
$image_uploading_errors = array(1 => 'Maximum file size in php.ini exceeded',
2 => 'Maximum file size in HTML form exceeded',
3 => 'Only part of the file was uploaded',
4 => 'No file was selected to upload.');
//Get the filename and size (validation of size is done in html part!)
$filename = $_FILES[SINGLE_IMAGE_UPLOAD_NAME]['name'];
$img_size = $_FILES[SINGLE_IMAGE_UPLOAD_NAME]['size'];
//Use the tmp name, to 'getimagesize' which returns an array of info (not just images size!) and also to get the data from the image
$info = getimagesize($_FILES[SINGLE_IMAGE_UPLOAD_NAME]['tmp_name']);
$data = file_get_contents($_FILES[SINGLE_IMAGE_UPLOAD_NAME]['tmp_name']);
//Get the mime type from the img_size (an array of info)
$mime_type = $info['mime'];
//Put all the info into a new image object
//(img_id, album_id, album_pos, name, low_res_mime, low_res_size, high_res_mime, high_res_size, available_sizes, date_uploaded, date taken, caption)
$img = new Image(NULL, NULL, NULL, $filename, NULL, NULL, $mime_type, $file_size, NULL, new DateTime(), NULL, NULL);
$img->set_high_res_data($data);
//Return the image!
return $img;
The Image class used is something that I've written myself, and all the variables like $mime_type do go correctly into the database.
I feel like this may be a repeat question, but I have looked on here, and none of the solutions (that I found) were useful!
EDIT:
The error is "The image '...' cannot be displayed because it contains errors." Where '...' is the file name.
I usually try to display the image with the html: wher %d is an integer.
The problem is that the image doesnt get siaplyed at all.
SINGLE_IMAGE_UPLOAD_NAME is a constant for the array key in $_FILES.
EDIT:
Not really a solution, but I changed to use the method to display images in this question and now it works:
how to display images from database in php?

Upload Multiple Files with FuelPHP

I currently have a script that allows me to upload 1 file to my server. It works great.
Here is a portion of the code I am using to do this:
// Custom configuration for this upload
$config = array(
'path' => DOCROOT.DS.'foldername/tomove/your/images',
'randomize' => true,
'ext_whitelist' => array('img', 'jpg', 'jpeg', 'gif', 'png'),
);
Upload::process($config);
// if a valid file is passed than the function will save, or if its not empty
if (Upload::is_valid())
{
// save them according to the config
Upload::save();
//if you want to save to tha database lets grab the file name
$value = Upload::get_files();
$article->filename = $value[0]['saved_as'];
}
I was now wondering, how do I loop through multiple files and upload these to my server?
I'm guessing using a foreach loop but I'm a little out of my depth with this I'm afraid.
Ultimately, I plan to store these filenames in a separate table on my database.
Many thanks for any help with this.
You already have the result in your code.
You already store it
$value = Upload::get_files();
so
$value = Upload::get_files();
foreach($value as $files) {
print_r($files);
}
And you will get everything what you need

Php WHILE loops only find one element

I got a problem with the following php code. It is supposed to list the items of a S3 bucket and find&delete files which contain a certain string in their filenames.
Problem is: only one file is deleted the others remain on the bucket after the execution of the script.
I can't find where the issue comes from so I ask you :/
$aS3Files = $s3->getBucket($bucketName); // list all elements in the bucket
$query = mysql_query("SELECT filename FROM prizes_media WHERE prize_id=" . $_POST["prizeId"]); // finds all filenames linked to the prize
while($media = mysql_fetch_array($query)){
// Find relevant files
while ( list($cFilename, $rsFileData) = each($aS3Files) ) { // reformat the bucket list into a table and reads through it
if(strpos($cFilename,$media['filename'])) {
$s3->deleteObject($bucketName, $cFilename); // deletes all files that contain $media['filename'] in their filename
}
}
}
// 2. Delete DB entry
mysql_query("DELETE FROM prizes WHERE id=" . $_POST['prizeId'] ); // deletes the entry correponding to the prize in the DB (deletes media table in cascade)
You may be getting false negatives on your if, you should be using this:
if(strpos($cFilename,$media['filename']) !== FALSE) { ...
Edit
Here is a different way to loop the bucket, based on the structure on your comment:
foreach($aS3Files as $filename => $filedata) {
if(strpos($filename, $media['filename']) !== FALSE) {
$s3->deleteObject($bucketName, $filename); // deletes all files that contain $media['filename'] in their filename
}
}

Categories