I have a project that needs to create files using the fwrite in php. What I want to do is to make it generic, I want to make each file unique and dont overwrite on the others.
I am creating a project that will record the text from a php form and save it as html, so I want to output to have generated-file1.html and generated-file2.html, etc.. Thank you.
This will give you a count of the number of html files in a given directory
$filecount = count(glob("/Path/to/your/files/*.html"));
and then your new filename will be something like:
$generated_file_name = "generated-file".($filecount+1).".html";
and then fwrite using $generated_file_name
Although I've had to do a similar thing recently and used uniq instead. Like this:
$generated_file_name = md5(uniqid(mt_rand(), true)).".html";
I would suggest using the time as the first part of the filename (as that should then result in files being listed in chronological/alphabetic order, and then borrow from #TomcatExodus to improve the chances of the filename being unique (incase of two submissions being simultaneous).
<?php
$data = $_POST;
$md5 = md5( $data );
$time = time();
$filename_prefix = 'generated_file';
$filename_extn = 'htm';
$filename = $filename_prefix.'-'.$time.'-'.$md5.'.'.$filename_extn;
if( file_exists( $filename ) ){
# EXTREMELY UNLIKELY, unless two forms with the same content and at the same time are submitted
$filename = $filename_prefix.'-'.$time.'-'.$md5.'-'.uniqid().'.'.$filename_extn;
# IMPROBABLE that this will clash now...
}
if( file_exists( $filename ) ){
# Handle the Error Condition
}else{
file_put_contents( $filename , 'Whatever the File Content Should Be...' );
}
This would produce filenames like:
generated_file-1300080525-46ea0d5b246d2841744c26f72a86fc29.htm
generated_file-1300092315-5d350416626ab6bd2868aa84fe10f70c.htm
generated_file-1300109456-77eae508ae79df1ba5e2b2ada645e2ee.htm
If you want to make absolutely sure that you will not overwrite an existing file you could append a uniqid() to the filename. If you want it to be sequential you'll have to read existing files from your filesystem and calculate the next increment which can result in an IO overhead.
I'd go with the uniqid() method :)
If your implementation should result in unique form results every time (therefore unique files) you could hash form data into a filename, giving you unique paths, as well as the opportunity to quickly sort out duplicates;
// capture all posted form data into an array
// validate and sanitize as necessary
$data = $_POST;
// hash data for filename
$fname = md5(serialize($data));
$fpath = 'path/to/dir/' . $fname . '.html';
if(!file_exists($fpath)){
//write data to $fpath
}
Do something like this:
$i = 0;
while (file_exists("file-".$i.".html")) {
$i++;
}
$file = fopen("file-".$i.".html");
Related
I am successfully able to get random images from my 'uploads' directory with my code but the issue is that it has multiple images repeat. I will reload the page and the same image will show 2 - 15 times without changing. I thought about setting a cookie for the previous image but the execution of how to do this is frying my brain. I'll post what I have here, any help would be great.
$files = glob($dir . '/*.*');
$file = array_rand($files);
$filename = $files[$file];
$search = array_search($_COOKIE['prev'], $files);
if ($_COOKIE['prev'] == $filename) {
unset($files[$search]);
$filename = $files[$file];
setcookie('prev', $filename);
}
Similar to slicks answer, but a little more simple on the session front:
Instead of using array_rand to randomise the array, you can use a custom process that reorders based on just a rand:
$files = array_values(glob($dir . '/*.*'));
$randomFiles = array();
while(count($files) > 0) {
$randomIndex = rand(0, count($files) - 1);
$randomFiles[] = $files[$randomIndex];
unset($files[$randomIndex]);
$files = array_values($files);
}
This is useful because you can seed the rand function, meaning it will always generate the same random numbers. Just add (before you randomise the array):
if($_COOKIE['key']) {
$microtime = $_COOKIE['key'];
else {
$microtime = microtime();
setcookie('key', $microtime);
}
srand($microtime);
This does means that someone can manipulate the order of the images by manipulating the cookie, but if you're okay with that this this should work.
So you want to have no repeats per request? Use session. Best way to avoid repetitions is to have two arrays (buckets). First one will contains all available elements that your will pick from. The second array will be empty for now.
Then start picking items from first array and move them from 1st array to the second. (Remove and array_push to the second). Do this in a loop. On the next iteration first array won't have the element you picked already so you will avoid duplicates.
In general. Move items from a bucket to a bucket and you're done. Additionally you can store your results in session instead of cookies? Server side storage is better for that kind of things.
so the title is not full clear, my question , I'm using the code to rename the file from directory present in the server the problem is i have to use the HTML form and php to update the file name, i want to do this : there will be an option on every file for renaming it when i click on the option the box pops up and i have to type the new name for file and save it , any help will be appreciated. (before down voting think about the question.)
The code that I'm using to update the file name
<?php
include("configuration.php");
$target = $_POST['filename'];
$newName = $_POST['newfilename'];
$actfoler = $_REQUEST['folder'];
$file = "files/users/";
$new ="files/users/";
$renameResult = rename($file, $new);
// Evaluate the value returned from the function if needed
if ($renameResult == true) {
echo $file . " is now named " . $new;
} else {
echo "Could not rename that file";
}
header("Location:".$_SERVER["HTTP_REFERER"]);
?>
Try changing these lines:
$file = "uploads/$loggedInUser->username$actfolder/$target";
$new ="uploads/$loggedInUser->username$actfolder/$newName";
To:
$file = "uploads/{$loggedInUser->username}{$actfolder}/{$target}";
$new ="uploads/{$loggedInUser->username}{$actfolder}/{$newName}";
To explain why:
You are using variables inside a string, which means you will want to tell PHP where the variable ends. Especially when referencing objects or arrays, but also when you are placing variables right next to each other. I'm guessing PHP evaluated your original line to uploads/[Object]->usernamePizza/newname
I don't think you can call object properties in a string as you do.
try replace these lines :
$file = "uploads/".$loggedInUser->username."$actfolder/$target";
$new ="uploads/".$loggedInUser->username."$actfolder/$newName";
You may think about echoing $file and $new to confirm the path is nicely built.
On a side note, I'd recommend to really check the entries because this code can obviously lead to major security issues.
I hope someone can help me with this php code.
At the moment its just saving an image with the file name "img.png" to the server but with every time a new canvas screenshot is taken the image is just overwritten.
My aim is to create a new unique (like numbered chronological by time taken) file name for the images with every new screenshot and save it on the server.
Here the php code so far:
$data = $_REQUEST['base64data'];
echo $data;
$image = explode('base64,',$data);
file_put_contents('img.png', base64_decode($image[1]));
Thank you.
regards
Try
$filename = 'img_'.date('Y-m-d-H-s').'.png';
file_put_contents($filename, base64_decode($image[1]));
This will save your file with a filename containing the current date and time, e.g.
img_2013-09-19-21-50.png
Try using a session variable to increment a counter like so:
<?php
session_start();
if(!isset($_SESSION['counter'])){
$_SESSION['counter'] = 0;
}
$_SESSION['counter']++;
$data = $_REQUEST['base64data'];
echo $data;
$image = explode('base64,',$data);
file_put_contents('img'.$_SESSION['counter'].'.png', base64_decode($image[1]));
?>
There's several ways to do it, but the easiest is just to add a timestamp/datestamp to the image name. Format the name as you want.
$img_name = 'img'.date('YmdHisu').'.png'; // Date & time with microseconds
$img_name = 'img'.time().'.png'; // unix timestamp
Leave the base64data structure use this one it will work fine.
$fileName = preg_replace('#[^a-z.0-9]#i', '', $fileName);
$image = explode(".", $fileName);
It will give a random number to each image file.
either create a UID using uniqid() function for the filename or create a folder with the name of the username who is uploading the file and leave the original filename. The disadvantage of the first one is that you will have to save the original filename somewhere to show to the user.
https://stackoverflow.com/a/4371988/2701758
**
/* simply for local time first give your continent then '/' then your country's
capital.
*/
date_default_timezone_set('Asia/Dhaka');
$now = new DateTime();
$now = $now->format("Y-m-d H:i:s.u");
$new_name = $now.$image;
/*what you want to add just write with dot,such
$new_name = 'img'.$now.$image;
*/
**
Each time someone lands in my page list.php?id=xxxxx it requeries some MySQL queries to return this:
$ids = array(..,..,..); // not big array - not longer then 50 number records
$thumbs = array(..,..,..); // not big array - not longer then 50 text records
$artdesc = "some text not very long"; // text field
Because the database from which I make the queries is quite big I would like to cache this results for 24h in maybe a file like: xxxxx.php in a /cache/ directory so i can use it in include("xxxxx.php") if it is present. ( or txt files !? , or any other way )
Because there is very simple data I believe it can be done using a few of PHP lines and no need to use memcached or other professional objects.
Becasuse my PHP is very limited can someone just place the PHP main lines ( or code ) for this task ?
I really would be very thankfull !
Caching a PHP array is pretty easy:
file_put_contents($path, '<?php return '.var_export($my_array,true).';?>');
Then you can read it back out:
if (file_exists($path)) $my_array = include($path);
You might also want to look into ADOdb, which provides caching internally.
Try using serialize;
Suppose you get your data in two arrays $array1 and $array2. Now what you have to do is store these arrays in file. Storing string (the third variable in your question) to file is easy, but to store an array you have to first convert it to string.
$string_of_array1 = serialize( $array1 );
$string_of_array2 = serialize( $array2 );
The next problem is the naming of cache files so that you can easily check if the relevant array is already available in cache. The best way to do this is to create an MD5 hash of your mysql query and use it as cache file name.
$cache_dir = '/path/cache/';
$query1 = 'SELECT many , fields FROM first_table INNER JOIN another_table ...';
$cache1_filename = md5( $query1 );
if( file_exists( $cache_dir . $cache1_filename ) )
{
if( filemtime( $cache_dir . $cache1_filename ) > ( time( ) - 60 * 60 * 24 ) )
{
$array1 = unserialize( file_get_contents( $cache_dir . $cache1_filename ) );
}
}
if( !isset( $array1 ) )
{
$array1 = run_mysql_query( $query1 );
file_put_contents( serialize( $array1 ) );
}
Repeat the above with the other array that should be stored in a separate file with MD5 of the second query used as the name of second cache file.
In the end, you have to decide how long your cache should remain valid. For the same query, there may change records in your mysql table that may make your file system cache outdated. So, you cannot just rely on unique file names for unique queries.
Important:
Old cache files have to be deleted. You may have to write a routine that checks all files of a directory and deletes the files older than n seconds.
Keep the cache dir outside the webroot.
Just write a new file with the name of the $_GET['id'] and contents of the stuff you want cached, and each time check to see if that file exists, else create one. Something like this:
$id = $_GET['id']
if (file_exists('/a/dir/' . $id)) {
$data = file_get_contents('/a/dir/' . $id);
} else {
//do mysql query, set data to result
$handle = fopen('/a/dir/' . $id, 'w+');
fwrite($handle, $data);
fclose($handle);
}
Based on #hamid-sarfraz answer, here is a solution used in PDO extended class, using json_encode/decode instead of serialize :
function get_assoc_c($query, $lifetime = 60*60*24) {
$c_dir = '/path/to/.cache/';
$c_filename = md5($query);
if(file_exists($c_dir . $c_filename)) {
if(filemtime($c_dir . $c_filename) > (time() - $lifetime)) {
return json_decode(file_get_contents($c_dir . $c_filename), true);
}
}
if(!isset($content)) {
if(!file_exists($c_dir))
mkdir($c_dir);
$stmt = $this->query($query);
$content = $stmt->fetchAll(PDO::FETCH_ASSOC);
file_put_contents($c_dir . $c_filename, json_encode($content));
return $content;
}
return false;
}
! Be aware to not use queries with arguments passed as variables (SQL injection).
I have the following code which uploads images to a rackspace cdn account.
error_reporting(E_ALL);
ini_set('display_errors', 1);
// include the API
require("cloudfiles.php") ;
// cloud info
$username = ''; // username
$key ='' ; // api key
$container = ''; // container name
ob_start();
$localfile = $_FILES['media']['tmp_name'];
$filename = $_FILES['media']['name'];
ob_flush();
// Connect to Rackspace
$auth = new CF_Authentication($username, $key);
$auth->authenticate();
$conn = new CF_Connection($auth);
// Get the container we want to use
$container = $conn->create_container($container);
// store file information
ob_flush();
// upload file to Rackspace
$object = $container->create_object($filename);
$object->load_from_filename($localfile);
$uri = $container->make_public();
//print "Your URL is: " . $object->public_uri();
$imagePageUrl = $object->public_uri();
//echo '<mediaurl>' . $imagePageUrl . '</mediaurl>';
ob_end_flush();
//echo '<mediaurl>' . $imagePageUrl . '</mediaurl>';
echo '<mediaurl>http://url.com/'.$filename.'</mediaurl>';
So each time i am uploading an image, say, image.jpg, it is overwriting the previous image.jpg in the container. I want to prevent that. Even if the filename is the same, is there a way to convert the filename to a random name, characters and then upload it?
Help plz.
Reading the other answers, while time() approach seems good, it does not provide real unique ids, its accuracy is only 1 second.
But PHP provides a way for having real unique IDS which is more accurate and provide a better solution. You could use it like:
$filename=uniqid().$_FILES['media']['tmp_name'];
Of course changing $_FILES['media']['tmp_name'] for whatever you prefer.
ok ... some code is missing ...
but you can try to give the new filename (uploaded image)... one name that is unique
simple example:
$filename = time()."-".$_FILES['media']['tmp_name'];
like this way your images will be named like '1333221458-my_image.jpg'
You can add the time to the filename, so assuming you will always have a .jpg:
$filename=explode(".",$filename);
$filename[0].="_".time();
$filename=implode(".",$filename);