I'm using following code format to change image name if it already exists on server. I want incremental image names if they already exist with the same name.
Ex: abc.png, abc_1.png, abc_2.png
function file_newname($path, $filename){
if ($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
$ext = substr($filename, $pos);
} else {
$name = $filename;
}
$newpath = $path.'/'.$filename;
$newname = $filename;
$counter = 1;
while (file_exists($newpath)) {
$newname = $name .'_'. $counter . $ext;
$newpath = $path.'/'.$newname;
$counter++;
}
return $newname;
}
Above code is working if image name is abc.png. If already an image is there on server with name abc_1.png and I run the code it generates image format as abc_1_1.png.
Expected output:
if already abc_1.png is present and I run the code $newname should return abc_2.png . How I can achieve it?
You just need to check what the string ends with, no need to use a regex for that. Take advantage of weak typing and is_numeric to find the value of any previous counter.
function file_newname($path, $filename){
if ($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
$ext = substr($filename, $pos);
} else {
$name = $filename;
}
$newpath = $path.'/'.$filename;
$newname = $filename;
// New code here:
if(file_exists($newpath)){
$counter = 1;
if($pos = strrpos($name, '_')) {
$oldcounter = substr($name, $pos + 1);
if(is_numeric($oldcounter)){
$counter = $oldcounter + 1;
$name = substr($name, 0, $pos);
}
}
$newname = $name . '_' . $counter . $ext;
$newpath = $path . '/' . $newname;
while (file_exists($newpath)) {
$newname = $name .'_'. $counter . $ext;
$newpath = $path.'/'.$newname;
$counter++;
}
}
return $newname;
}
I've simplified the functionality a bit so I could get it into a live example, but If you want to play around with the code in the replacement section that I added you can check it out here: http://ideone.com/xR1v0j Just modify the initial value of $name to see how it will react to different inputs.
Related
I use this Simple upload and resize image on PHP project to do my project.
https://gist.github.com/zeuxisoo/910107/483c7b6082dcc484d7b4cee21aad12650c53e416
but I don't know how to rename the file after upload.
I want to rename file and upload it into server as well as in database. The follow is code:
public function run() {
$total = count($this->files);
for($i=0; $i<$total; $i++) {
if (empty($this->files['name'][$i]) === false) {
if (move_uploaded_file($this->files['tmp_name'][$i], $this->store_directory.'/'.$this->files['name'][$i]) == false) {
$this->errors['type'] = "run";
$this->errors['file_name'] = $this->files['name'][$i];
}
}
}
return empty($this->errors);
}
I use a lot of method , eg basename
It can't to it, any idea?? Thanks
You can do this
public function run() {
$total = count($this->files);
for($i=0; $i<$total; $i++) {
if (empty($this->files['name'][$i]) === false) {
$tempName = explode(".", $this->files['name'][$i]);
$newName = "IMAGE_NAME"; //generate unique string to avoid conflict
$newfilename = $newName . '.' . end($tempName );
if (move_uploaded_file($this->files['tmp_name'][$i], $this->store_directory.'/'.$newfilename) == false) {
$this->errors['type'] = "run";
$this->errors['file_name'] = $this->files['name'][$i];
}
}
}
return empty($this->errors);
}
In $newName you can generate new name for your file.
Update
To avoid conflict use unique string each time when you generate the name.
Instead of using move_uploaded_file use it as per code example given below.
$temp = explode(".", $_FILES["file"]["name"]);
$newfilename = round(microtime(true)) . '.' . end($temp);
move_uploaded_file($_FILES["file"]["tmp_name"], "../img/imageDirectory/" . $newfilename);
Here is your solution
public function run(){
$total = count($this->files);
for($i=0; $i<$total; $i++){
if(empty($this->files['name'][$i]) === false){
$ext = substr(strtolower(strrchr($this->files['name'][$i], '.')), 1); //get the extension
$new_name = 'new-name'.date('dmY').$ext;
if (move_uploaded_file($this->files['tmp_name'][$i], $this->store_directory.'/'.$new_name) == false) {
$this->errors['type'] = "run";
$this->errors['file_name'] = $this->files['name'][$i];
}
}
}
return empty($this->errors);
}
I wrote a controller to upload files to a Directory. and I want if a file exists already in that Directory ,before moving , file name To be changed by increment one unit from last similar existent file name like this:
test.jpg
test(1).jpg
test(2).jpg
This is body of my Controller
$fileName = $file->getClientOriginalName();
$fileExt = $file->getClientOriginalExtension();
$destinationFolder = public_path('upload/userfiles/');
$num = 1;
$newName = $fileName;
while (file_exists($destinationFolder . $newName )) {
$newName = $fileName. '(' . $num . ')';
$num ++;
}
$file->move($destinationFolder, $newName . '.' . $fileExt);
But this does not work correctly and create file name like this :
test.jpg
test(1).jpg
test(1)(2).jpg
your problem is this:
$newName = $fileName;
at first is test.jpg
then you append the ($num++) so it becomes test(1).jpg
the next time its still test(1).jpg
and you append the ($num++) then it becomes test(1)(2).jpg
Thats it
This will work:
$fileName = $file->getClientOriginalName();
$fileExt = $file->getClientOriginalExtension();
$destinationFolder = public_path('upload/userfiles/');
$num = 1;
$newName = $fileName;
$appendNum = false;
while (file_exists($destinationFolder . $newName )) {
$appendNum = true;
$num ++;
}
if ($appendNum) $newName = $fileName. '(' . $num . ')';
$file->move($destinationFolder, $newName . '.' . $fileExt);
this work for me :
$current_name = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$only_name = explode('.', $current_name)[0];
$new_name = $current_name;
$destination = Storage::disk($link_directory)->path($folder);
$all_files = Storage::disk($link_directory)->listContents($folder);
$searchword = $only_name;
$matches = array_filter($all_files, function($var) use ($searchword) {
if(strpos($var['filename'], $searchword) !== FALSE) {
return $var;
}
});
if( is_array($matches) ){
$new_name = $only_name. '_' . count($matches).'.'.$extension;
}
$filename = Storage::disk($link_directory)->putFileAs($folder, $file, $new_name);
I have created a simple helper function that generates file name:
if (!function_exists('generateFilename')) {
/**
* Generate filename
*
* #param string $disk
* #param string $path
* #param UploadedFile $file
* #param integer $count
* #return string $filename
*/
function generateFilename(string $disk, string $path, UploadedFile $file, int $count = 0)
{
$extension = $file->getClientOriginalExtension();
$filename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) . ($count == 0 ? "." . $extension : "-{$count}." . $extension);
$filePath = Str::of($path)->finish(DIRECTORY_SEPARATOR)->finish($filename)->toString();
if (Storage::disk($disk)->exists($filePath)) {
$count++;
return generateFilename($disk, $path, $file, $count);
}
return $filename;
}
}
Goodafternoon, I made this script but I can't get where I'm wrong, it didn't save the PDF as I tried to program.
Thank you if there's any suggestion.
I know the problem is in the logic inside: function file_newname but I don't know where exactly.
Thank you in advance.
<?php
require('fpdf.php');
class PDF extends FPDF{
function Header(){
$this->Image('img/oet.png',10,6,30);
$this->SetFont('Helvetica','B',25);
$this->Cell(55);
$this->Cell(100,10,"TITLE",0,0,'C');
$this->SetFont('Helvetica','B',18);
$this->Ln(10);
$this->Cell(55);
$this->Cell(100,10,"SUBTITLE",0,0,'C');
$this->Ln(20);
}
function Footer(){
$this->SetY(-15);
$this->SetFont('Times','I',8);
$this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
}
function file_newname($filename){
if($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
$ext = substr($filename, $pos);
}else{
$name = $filename;
}
$newpath = 'docs/'.$filename;
$counter = 0;
while (file_exists("docs/")) {
$filename = $name .'_'. $counter . $ext;
$newpath = "docs/".$filename;
$counter++;
}
$this->Output("docs/".$filename);
}
}
$pdf = new PDF();
$pdf->AliasNbPages();
$pdf->AddPage();
$pdf->SetFont('Times','',12);
for($i=1;$i<=10;$i++){
$pdf->Cell(0,10,'Printing line number '.$i,0,1);
}
$pdf->Output();
$pdf->file_newname(date("Ymd").".pdf");
?>
You are delcaring your new filename after you attempt to output. Use this:
$filename = $pdf->file_newname(date("Ymd").".pdf");
$pdf->Output($filename, 'F');
Don't recall exactly what the F flag does in the output command, but that's how I have it in my scripts.
Here is the right solution:
function file_newname($filename){
if($pos = strrpos($filename, '.')) {
$name = substr($filename, 0, $pos);
$ext = substr($filename, $pos);
}else{
$name = $filename;
}
$newpath = 'documenti/'.$filename;
$counter = 0;
while (file_exists("documenti/".$filename)) {
$filename = $name .'_'. $counter . $ext;
$newpath = "documenti/".$newname;
$counter++;
}
$this->Output("documenti/".$filename);
$this->Output();
}
$pdf->file_newname(date("Ymd").".pdf");<<<<
I've been working with image uploading and am wondering why this isn't working correctly? It doesn't move/upload the file with the new name if it already exists.
if(isset($_REQUEST['submit'])){
$filename= $_FILES["imgfile"]["name"];
if ((($_FILES["imgfile"]["type"] == "image/gif")|| ($_FILES["imgfile"]["type"] == "image/jpeg") || ($_FILES["imgfile"]["type"] == "image/png") || ($_FILES["imgfile"]["type"] == "image/pjpeg")) && ($_FILES["imgfile"]["size"] < 20000000)){
$loc = "userpics/$filename";
if(file_exists($loc)){
$increment = 0;
list($name, $ext) = explode('.', $loc);
while(file_exists($loc)) {
$increment++;
$loc = $name. $increment . '.' . $ext;
$filename = $name. $increment . '.' . $ext;
}
move_uploaded_file($_FILES["imgfile"]["tmp_name"],"userpics/$loc");
}
else{
move_uploaded_file($_FILES["imgfile"]["tmp_name"],"userpics/$filename");
}
}
else{
echo "invalid file.";
}
}
You've included the folder path in $loc, then you attempt to move a file to userpics/$loc, which is probably incorrect. See the comments:
$filename = "example.jpg";
$loc = "userpics/$filename";
if(file_exists($loc)){
$increment = 0;
list($name, $ext) = explode('.', $loc);
while(file_exists($loc)) {
$increment++;
// $loc is now "userpics/example1.jpg"
$loc = $name. $increment . '.' . $ext;
$filename = $name. $increment . '.' . $ext;
}
// Now you're trying to move the uploaded file to "userpics/$loc"
// which expands to "userpics/userpics/example1.jpg"
move_uploaded_file($_FILES["imgfile"]["tmp_name"],"userpics/$loc");
} else {
// ...
As a general debugging tip, always check a function's return value to see if it was successful. Secondly, display the function's input values if it's failing. It will make debugging things a lot easier.
Try this:
$fullpath = 'images/1086_002.jpg';
$additional = '1';
while (file_exists($fullpath)) {
$info = pathinfo($fullpath);
$fullpath = $info['dirname'] . '/'
. $info['filename'] . $additional
. '.' . $info['extension'];
}
Thanks to here:Clickie!!
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);
}
}