I would like to save each newly generated PDF file with a unique filename to the "receipts" directory after generating the PDF using the FPDF library... As it is now, the PDF is overwritten each time. Can I append a time-stamp to the PDF filename? Example --->( /receipt_month-day-year-hour-seconds.pdf )
Absolute uniqueness desired, but not super critical.
$pdf->Output('receipts/receipt.pdf', 'F');
An easy (but not foolproof) way of ensuring a filename is unique would be to add a microtime timestamp to the filename. Microtime includes thousanths of a second, so would probably work unless your site has a lot of traffic:
$pdf->Output('receipts/receipt-' . microtime(true) . '.pdf', 'F');
If you want your timestamp to be like receipt_12-26-2017.pdf, then:
$pdf->Output('receipts/receipt_' . date("m-d-Y") . '.pdf', 'F');
If you really want to ensure your filenames are unique per directory, you could do something like this:
<?php
function get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE)
{
static $_filedata = array();
if ($fp = #opendir($source_dir))
{
// reset the array and make sure $source_dir has a trailing slash on the initial call
if ($_recursion === FALSE)
{
$_filedata = array();
$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
}
while (FALSE !== ($file = readdir($fp)))
{
if (#is_dir($source_dir.$file) && strncmp($file, '.', 1) !== 0)
{
get_filenames($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE);
}
elseif (strncmp($file, '.', 1) !== 0)
{
$_filedata[] = ($include_path == TRUE) ? $source_dir.$file : $file;
}
}
return $_filedata;
}
else
{
return FALSE;
}
}
function force_unique_filename( $dir_list, $file_name, $x = 2 )
{
/**
* Dir list may be an array of file names, or in the case of
* cURL, the list may be supplied as a string. If an array, we
* just convert the array to a string so it is checked as a string.
*/
if( is_array( $dir_list ) )
{
$dir_list = implode( ' ', $dir_list );
}
while( strpos( $dir_list, $file_name ) !== FALSE )
{
// Use pathinfo to break apart the filename
$info = pathinfo( $file_name );
// Get the file extension of the file
$ext = '.' . $info['extension'];
// Get the name of the file without extension
$file_name = basename( $file_name, $ext );
// Remove the filename suffix before adding a new one
$pattern = '/\(\d+\)/';
$replacement = '';
$file_name = preg_replace( $pattern, $replacement, $file_name );
// Add new filename suffix
$file_name .= '(' . (string) $x . ')' . $ext;
// Increment the number we are using in a filename suffix "($x)"
$x++;
}
return $file_name;
}
// -----------------------------------------------------------------------
// This directory should be an absolute path...
$source_dir = './receipts';
// The desired filename
$filename = 'receipt_' . date("m-d-Y") . '.pdf';
// Get all of the filenames in this directory
$filenames = get_filenames( $source_dir, FALSE, FALSE );
// Get the unique filename
$unique_filename = force_unique_filename( $filenames, $filename );
$pdf->Output('receipts/' . $unique_filename, 'F');
Related
I want the script to go into the folder 'images', take every file, cut the first four characters and rename it.
PHP
<?php
$path = './images/';
if ($handle = opendir($path))
{
while (false !== ($fileName = readdir($handle)))
{
if($fileName!=".." && $fileName!=".")
{
$newName = substr($fileName, 4);
$fileName = $path . $fileName;
$newName = $path . $newName;
rename($fileName, $newName);
}
}
closedir($handle);
}
?>
This is how the files in the images folder are named:
0,78test-1.jpg
0,32test-2.jpg
0,43test-3.jpg
0,99test-4.jpg
and this is what i want them to look like:
test-1.jpg
test-2.jpg
test-3.jpg
test-4.jpg
The problem is the script cuts out the first 8, 12 or 16 characters, not four as i want it! So when i execute it my files look like this:
-1.jpg
-2.jpg
-3.jpg
-4.jpg
UPDATE
I also tracked the packages to make sure i am not executing the script multiple times. The script is only executed once!
A slightly different approach though essentially the same with the substr part this worked fine for tests on local system.
$dir='c:/temp2/tmpimgs/';
$files=glob( $dir . '*.*' );
$files=preg_grep( '#(\.jpg$|\.jpeg$|\.png$)#i', $files );
foreach( $files as $filename ){
try{
$path=pathinfo( $filename, PATHINFO_DIRNAME );
$name=pathinfo( $filename, PATHINFO_BASENAME );
$newname=$path . DIRECTORY_SEPARATOR . substr( $name, 4, strlen( $name ) );
if( strlen( $filename ) > 4 ) rename( $filename, $newname );
} catch( Exception $e ){
echo $e->getTraceAsString();
}
}
You may want to try this little Function. It would do just the proper renaming for you:
<?php
$path = './images/';
function renameFilesInDir($dir){
$files = scandir($dir);
// LOOP THROUGH THE FILES AND RENAME THEM
// APPROPRIATELY...
foreach($files as $key=>$file){
$fileName = $dir . DIRECTORY_SEPARATOR . $file;
if(is_file($fileName) && !preg_match("#^\.#", $file)){
$newFileName = preg_replace("#\d{1,},\d{1,}#", "", $fileName);
rename($fileName, $newFileName);
}
}
}
renameFilesInDir($path);
<?php
$path = './images/';
if ($handle = opendir($path))
{
while (false !== ($fileName = readdir($handle)))
{
if($fileName!=".." && $fileName!=".")
{
//change below line and find first occurence of '-' and then replace everything before this with 'test' or any keyword
$newName = substr($fileName, 4);
$fileName = $path . $fileName;
$newName = $path . $newName;
rename($fileName, $newName);
}
}
closedir($handle);
}
?>
I have this code that should rename images. It takes the title of the site and generates a name but if there is no title it just keeps the old name.
How can i make it so that instead of the title it just randoms the number insteed? so instead of "title.extension" it will be randomnumber.jpg ?
$tmp = download_url( $img );
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $img, $matches);
$newfn = str_replace(array("%2B", "%52", "%20", "%5"), "B", basename($matches[0]));
$oofnm = basename($matches[0]);
if($newfn != $oofnm) {
$newfn2 = str_replace(array(".jpg", ".png", ".gif"), "", $newfn);
$tmppath = pathinfo( $tmp ); // extract path parts
$newpth = $tmppath['dirname'] . "/". $newfn2 . "." . $tmppath['extension'];
rename($tmp, $newpth); // renames temp file on server
$tmp = $newpth;
}
$file_array['name'] = $newfn;
$file_array['tmp_name'] = $tmp;
// If error storing temporarily, unlink
if ( is_wp_error( $tmp ) ) {
#unlink($file_array['tmp_name']);
$file_array['tmp_name'] = '';
continue;
}
Just drop all unnecessary:
$path_parts = pathinfo($matches[0]);
$file_array['name'] = rand(0,time()/1000) . "." . $path_parts['extension'];
I am not sure why you are using time()/1000 as upper bound for rand function. I would rather use rand with fixed min and max args or even use more advanced mt_rand function.
But I would recommend you to use uniqid() function for unique file to generate unique file identifiers:
$file_array['name'] = uniqid() . "." . $path_parts['extension'];
I'm working on a system that uses images, and the images are named by a md5-ed email. And I'd like to add a -1 -2 etc after the newly uploaded image if an image with the md5-ed email name already exists. Here's my code:
public function upload() {
global $email;
$fileName = $_FILES['userfile']['name'];
$tmpName = $_FILES['userfile']['tmp_name'];
$fileSize = $_FILES['userfile']['size'];
$fileType = $_FILES['userfile']['type'];
$user = $_SESSION['user'];
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
$content = addslashes($content);
fclose($fp);
if(!get_magic_quotes_gpc()) {
$fileName = addslashes($fileName);
}
$new_file_name = md5($email);
$fileExists = file_exists("../lib/uploads/" . $new_file_name);
$query = mysql_query("SELECT * FROM avatars WHERE ( name='$fileName' ) OR ( name='$new_file_name' ) ");
$num_rows = mysql_num_rows($query);
if ( $fileExists ) {
$fileName = $new_file_name;
$first = 1;
$separator = '-';
while ( file_exists("../lib/uploads/" . $fileName) ) {
preg_match('/(.+)'.$separator.'([0-9]+)$/', $fileName, $match);
$new_file_name = isset($match[2]) ? $match[1].$separator.($match[2] + 1) :$fileName.$separator.$first;
$first++;
}
$fileName = $new_file_name;
} elseif ( empty( $fileName ) ) {
echo '<div class="error">Please Select a file first.</div>';
} else {
move_uploaded_file($_FILES["userfile"]["tmp_name"],
"lib/avatars/" . $fileName);
echo "<div class='success'>File $fileName Uploaded.</div>";
}
} // ends upload() function
But I don't know what's wrong, it uploads the image with it's original name. Not even with the md5-ed email as name.
In short
You've messed up your if statements.
In detail
This is very veryu very simple. In your last else (the one that executes when the file doesnt exist) you have
move_uploaded_file($_FILES["userfile"]["tmp_name"],
"lib/avatars/" . $fileName);
But if you trace back, you will see that $fileName is set to
$fileName = $_FILES['userfile']['name'];
and not the md5 of the email. You have to remove the final else condition and have its code execute EVERY time. Of course as long as the $fileName is not empty.
So your code should be:
if ( $fileExists ) {
$fileName = $new_file_name;
$first = 1;
$separator = '-';
while ( file_exists("../lib/uploads/" . $new_file_name ) ) {
preg_match('/(.+)'.$separator.'([0-9]+)$/', $new_file_name, $match);
$new_file_name = isset($match[2]) ? $match[1].$separator.($match[2] + 1) :$new_file_name.$separator.$first;
$first++;
}
}
// <----
// Moved this one outside, since it always executes
// ---->
$fileName = $new_file_name;
// <----
// Separated this if, since it has nothing to do with the above
// ---->
if ( empty( $fileName ) ) {
echo '<div class="error">Please Select a file first.</div>';
} else {
move_uploaded_file($_FILES["userfile"]["tmp_name"],
"lib/avatars/" . $fileName);
echo "<div class='success'>File $fileName Uploaded.</div>";
}
} // ends upload() function
How you can optimize it
This depends if you are expecting single users to have lot's of images. If this is NOT the case, then leave it as is.
Otherwise, you will quickly end up having to wait for a long time after uploading 10th, 20th photo.
One way to improve it would be to search for files in a directory that fit a pattern (in this case your md5). For example like this:
foreach (glob($md5 . "*") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
This way you instantly know if there are already files with this md5 and how many of them.
I've just watched these videos on displaying images from a directory and would like some help modifiying the code.
http://www.youtube.com/watch?v=dHq1MNnhSzU - part 1
http://www.youtube.com/watch?v=aL-tOG8zGcQ -part 2
What the videos show is almost exactly what I wanted, but the system I have in mind is for photo galleries.
I plan on having a folder called galleries, which will contain other folders, one each for each different photo sets ie
Galleries
Album 1
Album 2
I would like some help to modify the code so that it can identify and display only the directories on one page. That way I can convert those directories into links that take you to the albums themselves, and use the orignal code to pull the images in from there.
For those that want the video code, here it is
$dir = 'galleries';
$file_display = array('bmp', 'gif', 'jpg', 'jpeg', 'png');
if (file_exists($dir) == false) {
echo 'Directory \'', $dir , '\' not found!';
} else {
$dir_contents = scandir($dir);
foreach ($dir_contents as $file) {
$file_type = strtolower(end(explode('.', $file)));
if ($file !== '.' && $file !== '..' && in_array($file_type, $file_display) == true) {
echo '<img src="', $dir, '/', $file, '" alt="', $file, '" />';
}
}
}
You need to use a function like this to list all of the directories:
function getDirectory( $path = '.', $level = 0 ){
$ignore = array( 'cgi-bin', '.', '..' );
// Directories to ignore when listing output. Many hosts
// will deny PHP access to the cgi-bin.
$dh = #opendir( $path );
// Open the directory to the handle $dh
while( false !== ( $file = readdir( $dh ) ) ){
// Loop through the directory
if( !in_array( $file, $ignore ) ){
// Check that this file is not to be ignored
$spaces = str_repeat( ' ', ( $level * 4 ) );
// Just to add spacing to the list, to better
// show the directory tree.
if( is_dir( "$path/$file" ) ){
// Its a directory, so we need to keep reading down...
echo "<strong>$spaces $file</strong><br />";
getDirectory( "$path/$file", ($level+1) );
// Re-call this same function but on a new directory.
// this is what makes function recursive.
} else {
echo "$spaces $file<br />";
// Just print out the filename
}
}
}
closedir( $dh );
// Close the directory handle
}
Then, pass the directory a user selected in as your $dir variable to the function you currently have.
I can't test any code right now but would love to see a solution here along the lines of:
$directory = new RecursiveDirectoryIterator('path/galleries');
$iterator = new RecursiveIteratorIterator($directory);
$regex = new RegexIterator($iterator, '/^.+\.(bmp|gif|jpg|jpeg|png)$/i', RecursiveRegexIterator::GET_MATCH);
SPL is powerful and should be used more.
The RecursiveDirectoryIterator provides an interface for iterating recursively over filesystem directories.
http://www.php.net/manual/en/class.recursivedirectoryiterator.php
myFolderi have thousands of image files that have keyword text for the name. i am trying to read from the list of images and upload the text into a dB field. the problem is that some of the text has utf8 characters like l’Été that show up like this ��t�
how can i read foreign characters so that the accents will insert into the dB field?
this is how im handling it now
function ListFiles($dir) {
if($dh = opendir($dir)) {
$files = Array();
$inner_files = Array();
while($file = readdir($dh)) {
if($file != "." && $file != ".." && $file[0] != '.') {
if(is_dir($dir . "/" . $file)) {
$inner_files = ListFiles($dir . "/" . $file);
if(is_array($inner_files)) $files = array_merge($files, $inner_files);
} else {
array_push($files, $dir . "/" . $file);//$dir = directory name
//array_push($files, $dir);
}
}
}
closedir($dh);
return $files;
}
}
foreach (ListFiles('../../myDirectory') as $key=>$file){
//$file = preg_replace( '#[^\0-\x80]#u',"", $file );
echo $file ."<br />";
}
this is producing the same result
$str = "l’Été";
utf8_decode($str);
echo $str;
This solution may work for you, it will loop through all files in a directoy and then recursivly through any directories found until it ends up with a massive array of files.
Ive added some points you may wish to change, eg either mutli or single dimension arrays ( all depend on if you may want to maintain the folder structure.
and also if you want the file extention to be saved when you save the file name to db.
Code
function recursive_search_dir($dir) {
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if (in_array($file,array(".","..")))
continue; // We dont want to do anything with parent / current directory.
if (is_dir($file)) {
$result[] = recursive_search_dir($file); // Multi-dimension
# OR
array_merge($result,recursive_search_dir($file));// Single-dimension if you dont care about folder structure.
} else {
$result[] = utf8_decode($file); // full file name ( includes extention )
# OR
$result[] = utf8_decode(filename($file,PATHINFO_FILENAME)); // if you only want to capture the name and not the extention.
}
}
closedir($handle);
}
return $result;
}
$files = recursive_search_dir("."); // recursively searcht the current directory.