PHP: How to generate indexed name with string in file output? - php

Actually I'm using uniqid(); to generate random names:
$file = UPLOAD_DIR . uniqid() . '.png';
The output looks like:
53bd02cdc6b9b.png
53bd02cdc6bd8.png
53bd0320aafbc.png
53bd0320aaff7.png
53bd03e89b8df.png
I want to change these names each file as output:
picture_0001.png
picture_0002.png
picture_0003.png
picture_0004.png
picture_0005.png
Do you have better ideas?

Your want to fix all your current images to the correct format (See # FĂ©lix Gagnon-Grenier answer), then once you done that you can do something like the following:
//get array of current images
$imgs = glob(UPLOAD_DIR.'*.png');
//select last image in array, strip out all non-alpha's then pad it with 4 0's
$next = str_pad(preg_replace("/[^0-9]/","", end($imgs))+1, 4, "0", STR_PAD_LEFT);
$file = UPLOAD_DIR.'picture_'.$next.'.png';
Edit
See comments - file based counter
$count_file = UPLOAD_DIR.'count.txt'; //or put somewhere else
//make count file if not exists
if(!file_exists($count_file)){
file_put_contents($count_file,0);
}
//get last image count + 1
$next = file_get_contents($count_file)+1;
//set file var
$file = UPLOAD_DIR.'picture_'.sprintf("%04s",$next).'.png';
//update counter
file_put_contents($count_file, $next);

well, since it hurts your feeling, you seem to be a human being, and I care for human beings. there you go:
I don't know any context, so this may be wildly far from what you actually need.
say your directory is /home/dir
$i = 1;
foreach (scandir('/home/dir') as $file)
{if ($file == '.' || $file == '..') continue;
rename($file,'picture_' . str_pad($i,4,'0',STR_PAD_LEFT) . '.png');
$i++;}
this will generate:
picture_0001.png
picture_0002.png
picture_0003.png
picture_0004.png
picture_0005.png
in place of your old files

Related

How to read filenames containing a number and only use those with less than or equal to a specified value, also how to make my 'cache' more efficient?

So I've got a couple of questions that I'm hoping someone will be able to help me with.
Firstly, I'm trying to create a page which parses information and organizes it by the hour into a table. At the moment my script parses the information with Simple HTML Dom and creates a text file for each hour called "hour_%time%.txt" (e.g. hour_02.txt, hour_14.txt, hour_22.txt). Each file will contain the parsed information as a table row.
How would I go about only using the files with times earlier than the current hour, so if the current hour was 9am, only files ending with equal to or less than 09 would be used? I was trying to use either explode or preg_match but I couldn't get it to work.
My code at the moment looks like so:
date_default_timezone_set('UTC');
$currentHour = date('H');
$cache_file = 'cache/hour_'.$currentHour.'.txt';
$data = '<tr><td>'.date('H:00').'</td><td>'.$firmato_count.'</td><td>'.$inviato_count.'</td><td>'.$positive_count.'</td><td>'.$negative_count.'</td></tr>';
file_put_contents($cache_file, $data);
echo '<table class="table"><tbody>';
echo '<tr><th>Time</th><th>Firmato</th><th>Inviato</th><th>Positive</th><th>Negative</th></tr>';
$files = glob("cache/hour_*.txt");
foreach($files as $txt){
$hourlyfile = file_get_contents($txt);
echo $hourlyfile;
}
echo '</table></tbody>';
And secondly, I'm fully aware this isn't the best way to do this but I couldn't figure out a better way myself. Can anyone suggest a more efficient way to store the parsed data and access it? Is it possible to use a single file? I did consider appending the same file however as my page will update frequently it ended up adding multiple lines of data for the same hour. Each file contains a string like so:
<tr><td>10:00</td><td>21</td><td>58</td><td>4</td><td>43</td></tr>
Any help is appreciated.
First convert your String of the hour to a number
[PHP]
$currentHour = intval($currentHour);
next compare
if($currentHour <= 9){ // < for less and <= for less and equal
doStuff
}
This only will display the file of the exact hour. Tell me if doesn't work for edit it.
date_default_timezone_set('UTC');
$currentHour = intval(date('H'));
$cache_file = 'cache/hour_'.$currentHour.'.txt';
$data = '<tr><td>'.date('H:00').'</td><td>'.$firmato_count.'</td><td>'.$inviato_count.'</td><td>'.$positive_count.'</td><td>'.$negative_count.'</td></tr>';
file_put_contents($cache_file, $data);
echo '<table class="table"><tbody>';
echo '<tr><th>Time</th><th>Firmato</th><th>Inviato</th><th>Positive</th><th>Negative</th></tr>';
$files = glob("cache/hour_*.txt");
if($currentHour == $currentHour){
foreach($files as $txt){
$hourlyfile = file_get_contents($txt);
echo $hourlyfile;
}
}
echo '</table></tbody>';
I ended up creating a variable called $globSearch and used if/elseif to create a search string based on the current hour. My code now looks like this:
date_default_timezone_set('UTC');
$currentDate = date('d/m/Y');
$currentHour = intval(date('H'));
$cache_file = 'cache/hour_'.$currentHour.'.txt';
$data = '<tr><td>'.date('H:00').'</td><td>'.$firmato_count.'</td><td>'.$inviato_count.'</td><td>'.$positive_count.'</td><td>'.$negative_count.'</td></tr>';
file_put_contents($cache_file, $data);
echo '<table class="table"><tbody>';
echo '<tr><th>Time</th><th>Firmato</th><th>Inviato</th><th>Positive</th><th>Negative</th></tr>';
if ($currentHour <= 9) {
$globSearch = "{cache/hour_[0][0-".$currentHour."].txt}";
} elseif ($currentHour >= 10 && $currentHour <= 19) {
$splitInt = str_split($currentHour);
$globSearch = "{cache/hour_[0][0-9].txt,cache/hour_[1][0-".$splitInt[1]."].txt}";
} elseif ($currentHour >= 20 && $currentHout <= 23) {
$splitInt = str_split($currentHour);
$globSearch = "{cache/hour_[0][0-9].txt,cache/hour_[1][0-9][2-".$splitInt[1]."].txt}";
}
//$files = glob("{cache/hour_[0][0-9].txt,cache/hour_[1][0-3].txt}", GLOB_BRACE);
$files = glob($globSearch, GLOB_BRACE);
foreach ($files as $txt) {
$hourlyfile = file_get_contents($txt);
echo $hourlyfile;
}
echo '</table></tbody>';
Thanks for replying Ruben and COOLGAMETUBE, much appreciated.

Replace character at a given position without affecting another similar character within the filename

I have this kind pdf filename,
20160.pdf
and I would like to replace 0 at position 4 count start to 0, I tried using something like this,
$filename[0] = "20160";
$filename[1] = "pdf";
$adds = 1;
$new_filename = str_replace($filename[0][4], $adds, $filename[0]) . '.' . $filename[1];
where 4 in $filename[0][4] generated by getting the string length of filename[0].
Question is how to replace character at position 4 only without affecting another similar character within the filename?
Here you go!
$filename[0] = "20160";
$filename[1] = "pdf";
$adds = 1;
$filename[0][strlen($filename[0]) - 1] = $adds;
echo $newfilename = $filename[0].'.'.$filename[1];
And the output is "20161.pdf"

How to link to an image in PHP flatfile with accents in the filename

The images don't load when I use accents in the title. There is nothing wrong with the charset but with the special characters breaking the path to the file.
I just need Spanish and French accents, but I don't like the solution of replacing all the characters one by one. I don't manage to do it any other way, any suggestion?
<?php
$dir = 'img/'; // Directory for images
$filetype = '*.*'; // Files
$allow = array('jpg', 'gif'); // Files allowed in the array
$files = glob($dir.$filetype);
$newest_images_first = true;
$files = array_reverse($files); // Sort files in reverse
$i=0;
$open = opendir($dir);
// Get filenames from directory, get extension and if the extension is valid, store in array using numerical indexing
while (($file=readdir($open))!==false) {
$ext=str_replace('.', '', strrchr($file, '.'));
if (in_array($ext, $allow))
$list[$i++]=$file; }
$perPage= 20; // Number of images per page
$total=count($list); // Number of images to show in total
$pages=ceil($total/$perPage); // Number of pages: the number of images divided by how many per page
$thisPage=isset($_GET['pg'])?$_GET['pg']-1:0; // did user select a specific page? Note, pages on web are counted from 1 (not zero) so must subtract 1 for correct indexing
$start=$thisPage*$perPage; // calculate starting index into list of filenames
$pageNumber= $thisPage+1;
$perRow= 1; // Number images per row
$imgCnt=0; // used to count number of images displayed and hence whether to wrap page. note, could use "for" index $i but this is computationally quicker
for ($i=$start;$i<$start+$perPage;$i++) {
// may be too few images to fill page, so check if we have a valid array index. if we don't output empty table cell so fussy browsers
// don't mis-display table due to missing cells
echo "<div class='item' 'hyphenate'>";
if (isset($list[$i])) {
echo "<figure>";
echo '<div class="photo">';
// Functions before alt attribute
$exif = exif_read_data($files[$i], 0, true); // Fetch Exif metadata
error_reporting(E_ERROR | E_PARSE); // Avoid warnings when trying to get exif data from PNG files
$title = substr($files[$i],strlen($dir),strrpos($files[$i], '.')-strlen($dir)); // Get filename, ignore path and text since the last '.'
$title = str_replace( array( '%', '-'), " ", $title); // Replace symbols with a space
$title = substr($title, 5); // Substract first 5 characters
$title = str_replace( array('', '_'), "", $title); // Replace items with nothing
// Image
echo '<img src="'.$files[$i].'" alt="'.$title.'" onload="this.width*=0.6">';
echo "</div>"; // Photo
echo "<figcaption>";
// Title
$title = preg_replace('/\'([^\']+)\'/', '<em>$1</em>', $title); // Make italics from anything within single quotes
echo '<h2>'."". $title .'</h2>'; // Show title
echo '<p>';
echo "".$exif['IFD0']['ImageDescription'].""; // Filter to IFD0 and ImageDescription
echo '</p>';
echo "</figcaption>";
echo "</figure>";
echo "</div>"; // item
}else {
echo "<td></td>"; // create an empty td
}
$imgCnt+=1; // increment images shown
if ($imgCnt%$perRow==0) // if image count divided by number to show per row has no remainder then it's time to wrap
echo "</tr><tr>";
}
echo "</tr>";
closedir($open);
?>
First of all, checking web server's access/error log probably will show you what problematic URLs had been sent from the browser and how they had failed.
The problem might be related to the encoding of the URL. Characters allowed in URLs are limited, and need to be encoded(escaped) otherwise.
I would like to try changing this:
echo '<img src="'.$files[$i].'" alt="'.$title.'" onload="this.width*=0.6">';
to
$filename = basename($files[$i]); // get the name part
$filename = urlencode($filename); // escape for URL
echo '<img src="' . $filename. '.' . $ext . '" alt="'.$title.'" onload="this.width*=0.6">';

How to start list of names from name "image100" and set limit 100 next names?

I have a script:
foreach(glob('/res/images/*.jpg') as $filename)
{
$filename = basename($filename, ".jpg");
$items = "$filename<br>";
}
return $items;
output is a file names:
image1
image2
...
image16354327
Question:
How to start list of names from name image100 and set limit 100 next names?
Try:
foreach(array_slice(glob('/res/images/image100*.jpg'), 0, 100) as $filename)
{
$filename = basename($filename, ".jpg");
$items = "$filename<br>";
}
How about modifying your pattern like this:
glob('/res/images/image1{0..9}{0..9}.jpg')
I've never actually used brace expansion with glob but this should get you image100.jpg, image101.jpg, image102.jpg, on up to image199.jpg. Is that what you're looking for?

pass files through php with rename

I have 1600 images, each 256px. These images have been sliced in photoshop from an image that is 10240px x 10240px in to the tiles. Problem is, photoshop has named them image_0001.png, image_0002.png...
I would like to rename these in to a usable file name such as image_x_y.png x being tile number in that row, y being tile number in that column...
And ideas how i can automate the renaming of these, or if not how i can pass these images through php, so that i can access image.php?x=2&y=1 ect...
thanks in advance
EDIT:
I have no permission to answer my own question but, used this as renaming would be required on every update. Not ideal...
<?php
$x=$_GET['x'];
$y=$_GET['y'];
$image=(($y-1)*40)+$x;
if ($image<10){
$image="0".$image;
}
$url="tiles/" . $image . ".jpg";
header("Location:" . $url);
?>
You could open the directory containing your files and then create a loop to access all images and rename them, like:
<?php
if ($handle = opendir('/path/to/image/directory')) {
while (false !== ($fileName = readdir($handle))) {
//do the renaming here
//$newName =
rename($fileName, $newName);
}
closedir($handle);
}
?>
Useful functions:
rename(),readdir(), readdir(), str_replace(), preg_replace()
Hope this helps!
You don't have to rename them, just calculate the "linear id" on every access.
so, assuming you have a 40 * 40 set of files, in image.php you'd have something like
$fileid = $x * 40 + y;
$filename = sprintf("image_%04d.png",$fileid);
// send the file with name $filename
What formula you need depends on how it was sliced, could as well be $y * 40 + x
The main advantage is that should your image be updated, it will be ready to use without the intermediate step of renaming the files.
Try this :
$dir = "your_dir";
$i = 0;
$j = 0;
$col = 5;
foreach(glob($dir . '/*') as $file)
{
rename($file, "image"."_".$j."_".$i);
$i++;
if($i % $col == 0)
{
$j++;
}
}
If you know for sure that the routine that converted your files always named the resulting images in the same order
i.e. top left = 0001 ...... Bottom right = 0016
Then it should be fairly simple to write a quick CLI script to go through and rename all your images.
Alternatively if you are going to use that same image converter again many times it may be simpler to make your image.php?x=1&y=2 script workout what file to serve then you wont need to do the renaming every time you get new images.
-read the soure folder with your images (http://php.net/manual/de/function.readdir.php)
-put the part of each imagename between "_" and "."
-parse it ($image_nr) as integer
-do the following:
$y = floor($image_nr/40);
$x = $image_nr%40;
finaly put each image in your destination directory with the new name
I Have not tested it but you could try using this:
$imagesInARow = 10240/256; //=> 40
$rows = 1600 / $imagesInARow; //=> 40
$imageIndex = 1;
for($i = 1; $i <= $rows; $i++) { // row iteration
for($j = 1; $j <= $imagesInARow; $j++) { // columns iteration
rename('image_'. str_pad($imageIndex, 4, '0', STR_PAD_LEFT).'.png',
"image_{$i}_{$j}.png");
$imageIndex ++;
}
}

Categories