php loop and skip over if file exists - php

I need some help with some PHP logic. I'm adding images to my directory where some images already exist. I'm trying to loop over the directory and skip over the names if they exist...hard to explain...here's what I have:
if(isset($_POST['imgName'])){
$artName = $_POST['imgName'];
if ($_FILES['file']['name'][0] != ""){
$num = 0;
for ($i=0; $i < count($_FILES['file']['name']); $i++){
$fileExt = str_replace("image/", ".", $_FILES['file']['type'][$i]);
$newFileName = "..//images/$num$artName$fileExt";
if (file_exists($newFileName)){
$num++;
$newFileName = "..//images/".$num.$artName.$fileExt;
move_uploaded_file($_FILES['file']['tmp_name'][$i], $newFileName);
}
}
}
}
I tried doing a while loop and a do while loop and I couldn't get it to work...maybe I was doing it wrong. Can I please get some advice? Thanks...
This is for a blog so the $artName is the article name...the $num [0] will be the main image and the rest will be the gallery images

WORKAROUND SOLUTION:
if(isset($_POST['imgName'])){
$artName = $_POST['imgName'];
if ($_FILES['file']['name'][0] != ""){
$pics = glob('..//images/*'.$artName.'*');
if($pics[0] != ""){
for($j=0; $j<count($pics); $j++){
$path = pathinfo($pics[$j]);
$ext = $path['extension'];
rename($pics[$j], "..//images/".$j.$artName.".".$ext);
}
}
$num = count($pics);
for ($i=0; $i < count($_FILES['file']['name']); $i++){
$fileExt = str_replace("image/", ".", $_FILES['file']['type'][$i]);
$newFileName = "..//images/$num$artName$fileExt";
move_uploaded_file($_FILES['file']['tmp_name'][$i], $newFileName);
$num++;
}
}
}
The workaround I came up with is checking the images related to the article which are already in the directory and renaming them. Then using the count(of images in the directory) and setting that to the $num and using the $num as part of the new image name...this way there are no duplicates. It there's a better solution, I'd love to hear it...

Related

Multi image upload validate by php

i modified my upload code based on this post https://stackoverflow.com/a/30074716/14787718 (its working code)
but my code does not work, please help.
my full code here: https://sandbox.onlinephpfunctions.com/code/c62b6bdf6fadd5aff63b2e7e65e75c1075d1dbb0
<?php
if (isset($_POST['upload']) && $_FILES['image']['error']==0) {
$j = 0; //Variable for indexing uploaded image
for ($i = 0; $i < count($_FILES['image']['name']); $i++) {//loop to get individual element from the array
$allow_ext = array('png','jpg','gif','jpeg','bmp','tif');
$allow_type = array('image/png','image/gif','image/jpeg','image/bmp','image/tiff');
$image_name = $_FILES['image']['name'][$i];
$image_type = getimagesize($_FILES['image']['tmp_name'][$i]);
$image_name = explode('.',$image_name);
$ext = end($image_name);
$j = $j + 1;//increment the number of uploaded images according to the files in array
if(in_array($ext, $allow_ext) && in_array($image_type['mime'], $allow_type)){
list($width, $height, $mime) = getimagesize($_FILES['image']['tmp_name'][$i]);
if ($width>0 && $height>0) {
$upload = move_uploaded_file($_FILES['image']['tmp_name'][$i], "uploads/".$_FILES['image']['name'][$i]);
if ($upload) {
echo '<p>File Uploaded: View Image</p>';
}
} else {
echo 'Error: Only image is allowed!';
}
} else {
echo 'Error: Invalid File Type!';
}
}
}
?>
thank you!
first move the Jquery call to place it before bootstrap:
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.0/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.0/js/bootstrap.min.js'></script>
And at your first test : if (isset($_POST['upload']) && $_FILES['image']['error']==0). $_FILES['image']['error'] is an array.
Delete this test to keep only if ( isset($_POST['upload']) )
Add this test in you for step:
for ($i = 0; $i < count($_FILES['image']['name']); $i++) {//loop to get individual element from the array
if ($_FILES['image']['error'][$i]==0) {
Tested, it works fine!

Rename each selected files differently using php

My problem is when I select multiple files, it renames all the selected files to the same, but I want to rename each selected files a bit differently and insert into the MySQL and the local folder.
For example
First Selected File Would be:
1_$date_$rand_.png
Second Selected File Would be:
2_$date_$rand_.pnp
And so on...
I also tried with random number but it will rename each selected file to the same as well. I can't figure out how should I do it with loop.
My php code to rename a file and upload into database:
$rand = rand(0, 99999);
$date = date('Y_m_d-H_i_s-a', time());
$count = 0;
$path = "../../images/"; // Upload directory=
$filename = $date."_".$rand.'.';
foreach ($image as $f => $imgname) {
$ext = end((explode(".", $imgname)));
mysqli_query($conn,"INSERT INTO images(name)
VALUES ('$filename$ext')");
if(move_uploaded_file($_FILES["image"]["tmp_name"][$f], "$path/$filename$ext")) {
$count++; // Number of successfully uploaded files
}
}
Use file_exists() and a counter
$rand = rand(0, 99999);
$date = date('Y_m_d-H_i_s-a', time());
$count = 0;
$fileCounter = 0;
$path = "../../images/"; // Upload directory=
$filename = $date."_".$rand.'.';
foreach ($image as $f => $imgname) {
$ext = end((explode(".", $imgname)));
$fileCounter=1;
$fullFilename = "$filename$fileCounter$ext" ;
while(file_exists($path . '/'. $fullFilename)){
$fileCounter ++;
$filename = "$filename$fileCounter$ext" ;
}
mysqli_query($conn,"INSERT INTO images(name) VALUES ('$fullFilename')");
if(move_uploaded_file($_FILES["image"]["tmp_name"][$f],$path . '/'.$fullFilename )) {
$count++; // Number of successfully uploaded files
}
}

Is it possible to add action only at LOOP's final round?

I want to do redirect to other page after finish the loop
something like this
for($i = 0; $i < 5; $i++)
{
echo $i;
header('Location: home.php'); // do this if finish the loop
}
Note : My case the redirect has to be in loop because my real code is about upload multiple files in loop and check file type in loop so I want to not redirect if it has wrong filetype, and if upload correctly, redirect to home.php page too. but the problem is when I upload correctly in first round loop it will redirect to home page without doing upload residual files.
and If I put redirect outside of loop , the errormessage of filetype will not show because it will redirect to home only.
$path_upload = 'images/cover/';
$count = count($_FILES["images"]["name"]);
$allowed_types = array("image/gif", "image/jpeg", "image/png");
$nl = PHP_EOL.'<br>'; // Linux: \n<br> Window: \r\n<br>
$arr_newname = array();
for($i=0; $i < $count; $i++)
{
$file_type = $_FILES["images"]['type'][$i];
$file_name = $_FILES["images"]['name'][$i];
$file_size = $_FILES["images"]['size'][$i];
$file_error = $_FILES["images"]['error'][$i];
$file_tmp = $_FILES["images"]['tmp_name'][$i];
if($_FILES["images"]["name"][$i] != "")
{
if (in_array($file_type, $allowed_types) && $file_size < 2000000)
{
if ($file_error > 0) {
echo 'Upload file:'.$file_name.' error: '.$file_error.$nl;
} else {
$ext = explode('.', $file_name); // explode dots on filename
$ext = end($ext); // get last item of array
$newname = "album_id".$album_id."_".date('Y-m-d')."_".($i+1).".".$ext;
$arr_newname[$i] = $newname;
$path_new_upload = $path_upload.$newname;
if(move_uploaded_file($file_tmp, $path_new_upload))
{
$data = array(
'front_pic'.($i+1) => $arr_newname[$i]
);
$this->db->where('album_id', $album_id);
$this->db->update('oav_album', $data);
redirect('home.php'); ////////THIS will stop the residual round of loop
}
}
}
else
{
echo 'Invalid file type to: '.$file_name.$nl;
// continue the code
}
}
}
redirect('home.php'); ////////IF I put this outside loop it will not show error` message but redirect to home
You can write the statement after the loop so it works at the end of the loop for one time. If you want to use last known $i value you can define $i before the loop and use it after the loop.
$i = 0
for ($i = 0; $i < $count; $i++){
//loop
}
$i--;//get last value
echo $i;
header('Location: home.php'); // do this if finish the loop

PHP Rename File name if Exists Append Number to End

I'm trying to rename the file name of an image when it's uploaded if it exists, say if my file name is test.jpg and it already exists I want to rename it as test1.jpg and then test2.jpg and so on. With the code I've written its changing my file name like so test1.jpg and then test12.jpg any advice on fixing this would be great thank!
PHP
$name = $_FILES['picture']['name'];
$actual_name = pathinfo($name,PATHINFO_FILENAME);
$extension = pathinfo($name, PATHINFO_EXTENSION);
$i = 1;
while(file_exists('tmp/'.$actual_name.".".$extension))
{
$actual_name = (string)$actual_name.$i;
$name = $actual_name.".".$extension;
$i++;
}
Here's a minor modification that I think should do what you want:
$actual_name = pathinfo($name,PATHINFO_FILENAME);
$original_name = $actual_name;
$extension = pathinfo($name, PATHINFO_EXTENSION);
$i = 1;
while(file_exists('tmp/'.$actual_name.".".$extension))
{
$actual_name = (string)$original_name.$i;
$name = $actual_name.".".$extension;
$i++;
}
Inspired from #Jason answer, i created a function which i deemed shorter and more readable filename format.
function newName($path, $filename) {
$res = "$path/$filename";
if (!file_exists($res)) return $res;
$fnameNoExt = pathinfo($filename,PATHINFO_FILENAME);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$i = 1;
while(file_exists("$path/$fnameNoExt ($i).$ext")) $i++;
return "$path/$fnameNoExt ($i).$ext";
}
Example:
$name = "foo.bar";
$path = 'C:/Users/hp/Desktop/ikreports';
for ($i=1; $i<=10; $i++) {
$newName = newName($path, $name);
file_put_contents($newName, 'asdf');
}
New version (2022):
function newName2($fullpath) {
$path = dirname($fullpath);
if (!file_exists($fullpath)) return $fullpath;
$fnameNoExt = pathinfo($fullpath,PATHINFO_FILENAME);
$ext = pathinfo($fullpath, PATHINFO_EXTENSION);
$i = 1;
while(file_exists("$path/$fnameNoExt ($i).$ext")) $i++;
return "$path/$fnameNoExt ($i).$ext";
}
Usage:
for ($i=1; $i<=10; $i++) {
$newName = newName2($fullpath);
file_put_contents($newName, 'asdf');
}
There are several ways for renaming image in PHP before uploading to the server.
appending timestamp, unique id, image dimensions plus random number etc.You can see them all here
First, Check if the image filename exists in the hosted image folder otherwise upload it. The while loop checks if the image file name exists and appends a unique id as shown below ...
function rename_appending_unique_id($source, $tempfile){
$target_path ='uploads-unique-id/'.$source;
while(file_exists($target_path)){
$fileName = uniqid().'-'.$source;
$target_path = ('uploads-unique-id/'.$fileName);
}
move_uploaded_file($tempfile, $target_path);
}
if(isset($_FILES['upload']['name'])){
$sourcefile= $_FILES['upload']['name'];
tempfile= $_FILES['upload']['tmp_name'];
rename_appending_unique_id($sourcefile, $tempfile);
}
Check more image renaming tactics
I checked SO and found a nice C# answer here, so I ported it for PHP:
['extension' => $extension] = pathinfo($filePath);
$count = 0;
while (file_exists($filePath) === true) {
if ($count === 0) {
$filePath = str_replace($extension, '[' . ++$count . ']' . ".$extension", $filePath);
} else {
$filePath = str_replace("[$count].$extension", '[' . ++$count . ']' . ".$extension", $filePath);
}
}

Rename all files in order in PHP

I have the following files:
1.jpg
2.jpg
3.jpg
4.jpg
When I remove 2.jpg, I want 3.jpg to become 2.jpg and 4.jpg to become 3.jpg
I tried a for loop with the rename function, but it does not seem to work:
for($a = $i;$a < $filecount;$a ++)
{
rename('photo/'.($a+1).'.jpg', 'photo/'. ($a).'.jpg');
}
Where $i is the number of the photo I just deleted.
List all files, sorted by name:
$files = glob('../photos/*');
Foreach file, rename it if necessary:
foreach($files as $i => $name) {
$newname = sprintf('../photos/%d.jpg', $i+1);
if ($newname != $name) {
rename($name, $newname);
}
}
Why don't you just remove the file you don't longer need and than rename all files that remain in the folder, starting with one. Like:
<?php
$fileToRemove= '3.jpg';
unlink($fileToRemove);
$cnt = 0;
if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
rename($file, ++$cnt+".jpg");
}
}
closedir($handle);
}
?>
This way, you are always sure that the sequence is correct. If you have a lot of files, you can of cource start renaming from the number of the file you are deleting.
I would have do it this way:
echo "<pre>";
$files = array('file1.jpg', 'file5.jpg', 'file7.jpg', 'file9.jpg');
function removeElement($array, $id){
$clone = $array; // we clone the array for naming usage
$return = array(); // the array returned for testing purposes
$j = 0;
foreach($array as $num => $file){ // loop in the elements
if($file != $id){ // check if the current file is not the element we want to remove
if($num == $j){ // if current element and '$j' are the same we do not need to rename that file
$return[] = "// #rename('".$file."', '".$file."'); -- do not rename";
} else { // if previously we have removed the file '$id' then '$j' should be -1 and we rename the file with the next one stored in '$clone' array
$return[] = "#rename('".$file."', '".$clone[($num-1)]."'); // rename";
}
} else { // this is for the file we need to remove, we also -1 current '$j'
$j--;
}
$j++;
}
return $return;
}
print_r(removeElement($files, 'file5.jpg'));
it seems rudimentary, but it works and is easy to read.
$filecount = 5;
$i = 2;
unlink('photo/'. $i . '.jpg');
for($i; $i < $filecount; $i++) {
rename('photo/'. ($i+1) .'.jpg', 'photo/'. $i . '.jpg');
}
die;

Categories