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);
}
}
Related
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
}
}
I've been looking in this for a day or two now.
When I upload multiple files to this script, "$finalfilename" give's me back multiple filenames from the second file.
Here's my code:
include ($_SERVER['DOCUMENT_ROOT'] . "/config/config.php");
$valid_extensions = array(
'jpeg',
'jpg',
'png',
'gif',
'bmp'
); // valid extensions
$path = $_SERVER['DOCUMENT_ROOT'] . '/assets/uploads/'; // upload directory
$uploadOK = 1;
$album = strip_tags($_POST['newPostForm-Album']);
$i = 0;
foreach($_FILES['NEW-POST-FORM_IMAGES']['name'] as $file)
{
$imgname = $_FILES['NEW-POST-FORM_IMAGES']['name'][$i];
$tmpname = $_FILES['NEW-POST-FORM_IMAGES']['tmp_name'][$i];
$timestamp = time();
$extension = strtolower(pathinfo($imgname, PATHINFO_EXTENSION));
$newfilename = sha1(time() . $i);
$finalfilename = $newfilename . "." . $extension;
if ($_FILES['NEW-POST-FORM_IMAGES']["size"][$i] > 500000)
{
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
if ($uploadOK)
{
if (in_array($extension, $valid_extensions))
{
$path = $path . strtolower($finalfilename);
if (move_uploaded_file($tmpname, $path))
{
// mysqli_query($con, "INSERT INTO posts VALUES('', '$album', '$finalfilename', '$timestamp')");
echo $_FILES['NEW-POST-FORM_IMAGES']['name'][$i];
}
else
{
echo "error!";
}
}
}
$imgname = "";
$tmpname = "";
$timestamp = "";
$extension = "";
$newfilename = "";
$finalfilename = "";
$i++;
}
As you can see, I tried resetting all the strings at the end before adding $i.
UPDATE
I tried using $file instead of $_FILES (echo $file['name'][$i];)
This gives me back this warning:
Illegal string offset 'name' in
also the output of the second file ($finalfilename) gives me 'filename'.extention'filename'.extention
ea5816965b01dae0b19072606596c01efc015334.jpeg21aa3008f90c89059d981bdc51b458ca1954ab46.jpg
Wich need to be separated.
I need to only get the filename of each file seperatly.
Thank you!
Problem is in $path variable.
Put $path = $_SERVER['DOCUMENT_ROOT'] . '/assets/uploads/'; into the loop. You can remove variable reseting from the end too.
foreach ($_FILES['NEW-POST-FORM_IMAGES']['name'] as $file) {
$path = $_SERVER['DOCUMENT_ROOT'] . '/assets/uploads/';
$imgname = $_FILES['NEW-POST-FORM_IMAGES']['name'][$i];
$tmpname = $_FILES['NEW-POST-FORM_IMAGES']['tmp_name'][$i];
$timestamp = time();
$extension = strtolower(pathinfo($imgname, PATHINFO_EXTENSION));
$newfilename = sha1(time() . $i);
$finalfilename = $newfilename . "." . $extension;
if ($_FILES['NEW-POST-FORM_IMAGES']["size"][$i] > 500000)
{
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
if ($uploadOK)
{
if (in_array($extension, $valid_extensions))
{
$path = $path . strtolower($finalfilename);
if (move_uploaded_file($tmpname, $path))
{
// mysqli_query($con, "INSERT INTO posts VALUES('', '$album', '$finalfilename', '$timestamp')");
echo $_FILES['NEW-POST-FORM_IMAGES']['name'][$i];
}
else
{
echo "error!";
}
}
}
$i++;
}
There are more thing to update, instead of foreach for/while would be better here, or using foreach in else way (use $file in the loop body), etc. Moving $path into loop is easiest way how to fix your problem.
Can someone tell me why this php code doesn't work? It doesn't chek if file_exists, but it just run the code. Sorry for my bad (grammer) english, english is not my main langue :).
$files = glob("../templates/Default/*");
for ($i=0; $i<count($files); $i++) {
$src = $files[$i];
$fileName = $src;
$fileName = str_replace("../templates/Default/", "", $fileName);
$dirName = $fileName;
$dest = "../Sites/NewSite1/$fileName";
if(file_exists($fileName)){
copy($src, $dest);
echo $fileName;
}else{
$fileName = "../templates/Default/$dirName";
$fileName = str_replace("$dirName", "$dirName/*", $fileName);
$dFiles = glob($fileName);
for ($t=0; $t<count($dFiles); $t++) {
$src2 = $dFiles[$t];
copy($src2, $dest);
echo $src2;
}
}
}
if you want to check whether the file exists in the directory where you are trying to copy it to, then you need to provide file_exists() with the entire directory path, therefore do the following:
change this: if (file_exists($fileName)) {
to this: if (file_exists($dest)) {
Here is the right code: (it still need some tweeking).
$files = glob("../templates/Default/*");
for ($i=0; $i<count($files); $i++) {
$src = $files[$i];
$fileName = $src;
$fileName2 = str_replace("../templates/Default/", "", $fileName);
$dirName = $fileName2;
$dest = "../Sites/$websiteName/$fileName2";
if (!copy($src, $dest)) {
$fileName3 = "../templates/Default/$dirName/*";
$dest2 = "../Sites/$websiteName/$fileName2";
$dFiles = glob($fileName3);
for ($t=0; $t<count($dFiles); $t++) {
$src2 = $dFiles[$t];
$fileName4 = $src2;
$fileName4 = str_replace("../templates/Default/$dirName/", "", $fileName4);
mkdir("../Sites/$websiteName/$dirName");
$dest2 = "../Sites/$websiteName/$dirName/$fileName4";
copy($src2, $dest2);
}
}
}
I have a code that changes image names like in the windows systems. If there is a image like cup.jpg, the code changes the name into cup0.jpg.
The problem however, is when I'm uploading many images from array and only some of the images already exist and need to get the name changed.
What changes need to be made for this to work with multiple files?
for($i=0; $i<count($_FILES['upload']['name']); $i++) {
$target_file = $target_dir . basename($_FILES["upload"]["name"][$i]);
$images[] = basename($_FILES['upload']['name'][$i]);
}
if (file_exists($target_file)) {
$i = 0;
echo " Image exists, changing name.";
while (file_exists($target_file)) {
$extension = pathinfo($target_file, PATHINFO_EXTENSION);
$filename = pathinfo($target_file, PATHINFO_FILENAME);
$new_filename = $filename . $i . $iterator . '.' . $extension;
$target_file = $target_dir . $new_filename;
$i++;
$images[] = $new_filename;
}
}
I tried adding a loop but the code doesn't work if the array consists of new images and already existing images so only some of the images would need their names changed.
Here are you go:
$images = array();
for($i=0; $i<count($_FILES['upload']['name']); $i++) {
getUniqueName(basename($_FILES["upload"]["name"][$i]),$images);
}
function getUniqueName ($name, &$images) {
$i = 0;
$extension = pathinfo($name, PATHINFO_EXTENSION);
$filename = pathinfo($name, PATHINFO_FILENAME);
while (in_array($name, $images)) {
$name = $filename . $i . '.' . $extension;
$i++;
}
/* Need to define $target_dir here */
$i=0;
while (file_exists($target_dir.$name)) {
$name = $filename . $i . '.' . $extension;
$i++;
}
$images[]= $target_dir.$name;
}
I'm creating a function where users can upload multiple images and upload them to the server. Using a global variable for this matter works, but I've heard global variables are bad especially in OOP. So, I'm wondering what a good alternative would be? (I'm a starting PHP programmer, any detailed information is appreciated)
Code:
function addImgToNieuws($images){
if (isset($images) && $images != "") {
$countFiles = count($images["name"]);
for ($i = 0; $i < $countFiles; $i++) {
$fileName = $images["name"][$i];
$fileType = $images["type"][$i];
$fileSize = $images["size"][$i];
$fileError = $images["error"][$i];
$fileTmp = $images["tmp_name"][$i];
$kaboom = explode(".", $fileName);
$fileExt = end($kaboom);
$db_file_name = rand(100000, 999999) . "." . $fileExt;
$output = $this->db->real_escape_string($db_file_name);
global $string;
$string .= ",$output";
$string = substr($string, 1);
}
echo $string;
}
}
function addImgToNieuws($images){
if (isset($images) && $images != "") {
throw new Exception("bad input bro");
}
$countFiles = count($images["name"]);
$db_names = array();
for ($i = 0; $i < $countFiles; $i++) {
$fileName = $images["name"][$i];
$fileType = $images["type"][$i];
$fileSize = $images["size"][$i];
$fileError = $images["error"][$i];
$fileTmp = $images["tmp_name"][$i];
$kaboom = explode(".", $fileName);
$fileExt = end($kaboom);
$db_file_name = rand(100000, 999999) . "." . $fileExt;
$db_names[] = $this->db->real_escape_string($db_file_name)
}
return $db_names;
}
Assuming you wanted to get the $db_names. It's a little bit odd to do the escaping here, I would delay it until the very moment you insert it in the query.
If you really wanted the $db_names as a string you can do:
echo join(",", $obj->addImgToNieuws($images));