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'];
Related
I'm trying to copy an image using the path which is stored in my DB. I tried this but it throws "Array To String Conversion" error. I've never dealt with this before. Here's my code.
$record = AboutPageIntro::find($id);
$img_name = $record->image;
$ext = explode('.', $img_name);
Storage::disk('local')->copy(public_path($record->image), public_path('uploads/about_page/intro/' . uniqid() . '.' . $ext));
You're attempting to convert an array from explode('.', $img_name); to a string in the final line.
$record = AboutPageIntro::find($id);
$img_name = $record->image;
$ext = explode('.', $img_name); // This is an array like ['image_name', 'ext]
Storage::disk('local')->copy(
public_path($record->image),
public_path('uploads/about_page/intro/' . uniqid() . '.' . $ext[count($ext)-1])
); // You'll need to address the last item in the array by its index like this
That said, pathinfo(...) is the safer option here.
$record = AboutPageIntro::find($id);
$img_name = $record->image;
$ext = pathinfo($img_name, PATHINFO_EXTENSION);
Storage::disk('local')->copy(
public_path($record->image),
public_path('uploads/about_page/intro/' . uniqid() . '.' . $ext
);
I think its a simple problem of using explode as it will return an array of strings based on the dividing parameter.
I'm not too savvy with OOP but I can suggest using str_replace or trim to remove the '.'s in the $img_name variable.
$record = AboutPageIntro::find($id);
$img_name = $record->image;
$ext = str_replace('.',"",$img_name);
Storage::disk('local')->copy(public_path($record->image), public_path('uploads/about_page/intro/' . uniqid() . '.' . $ext));
I'm having a problem in my code, I am trying to append a number to a filename if filename already exists. It goes something like this
$explode = explode(".", $fileName);
$extension = end($explode);
$fileactualname = reset($explode);
$i = 0;
while (file_exists($location.$fileName)) {
$i++;
}
$fileName= $i.$fileName;
$name = $fileName;
$moveResult = move_uploaded_file($fileTmpLoc, $location . "/". $name);
if ($moveResult != true) {
#unlink($fileTmpLoc);
header('location: ' . URL . '?page=0&sort=name&type=desc&folder=uploads/&message=uploaderror');
}
Unfortunately for some reason $i wont increase its value by 1 every time it loops, instead it adds to the filename this way 1234filename.jpg my file name variable is after the loop and i cant understand why this is accruing. I am expecting to get ($i)filename.jpg a single number
AFTER RESTARTING MY LOCALSERVER IT STARTED WORKING WITH THE CODE PROVIDED BELOW DUUUH
You need to use the actual filename when you concat the number to it and not the one you already added a number to.
// not sure why you are splitting the filname up here
$explode = explode(".", $fileName);
$extension = end($explode);
$fileactualname = reset($explode);
$i = 0;
$fn = $fileName;
while (file_exists($location.$fn)) {
$i++;
// add number to actual filename
$fn = $i.$fileName;
}
$name = $fn;
$moveResult = move_uploaded_file($fileTmpLoc, $location . "/". $name);
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');
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.
is there any pretty solution in PHP which allows me to expand filename with an auto-increment number if the filename already exists? I dont want to rename the uploaded files in some unreadable stuff. So i thought it would be nice like this: (all image files are allowed.)
Cover.png
Cover (1).png
Cover (2).png
…
First, let's separate extension and filename:
$file=pathinfo(<your file>);
For easier file check and appending, save filename into new variable:
$filename=$file['filename'];
Then, let's check if file already exists and save new filename until it doesn't:
$i=1;
while(file_exists($filename.".".$file['extension'])){
$filename=$file['filename']." ($i)";
$i++;
}
Here you go, you have a original file with your <append something> that doesn't exist yet.
EDIT:
Added auto increment number.
Got it:
if (preg_match('/(^.*?)+(?:\((\d+)\))?(\.(?:\w){0,3}$)/si', $FILE_NAME, $regs)) {
$filename = $regs[1];
$copies = (int)$regs[2];
$fileext = $regs[3];
$fullfile = $FILE_DIRECTORY.$FILE_NAME;
while(file_exists($fullfile) && !is_dir($fullfile))
{
$copies = $copies+1;
$FILE_NAME = $filename."(".$copies.")".$fileext;
$fullfile = $FILE_DIRECTORY.$FILE_NAME;
}
}
return $FILE_NAME;
You can use this function below to get unique name for uploading
function get_unique_file_name($path, $filename) {
$file_parts = explode(".", $filename);
$ext = array_pop($file_parts);
$name = implode(".", $file_parts);
$i = 1;
while (file_exists($path . $filename)) {
$filename = $name . '-' . ($i++) . '.' . $ext;
}
return $filename;
}
Use that function as
$path = __DIR__ . '/tmp/';
$fileInput = 'userfile';
$filename = $path .
get_unique_file_name($path, basename($_FILES[$fileInput]['name']));
if (move_uploaded_file($_FILES[$fileInput]['tmp_name'], $filename)) {
return $filename;
}
You can get working script here at github page
Use file_exists() function and rename() function to achieve what you're trying to do!