I have this function, and this deletes textfiles after a certain age from my database automatically.
$r = new textfiles;
$db = new DB;
$currTime_ori = $db->queryOneRow("SELECT NOW() as now");
...
if($this->site->textfilesretentiondays != 0)
{
echo "PostPrc : Deleting textfiles older than ".$this->site->textfilesretentiondays." days\n";
$result = $db->query(sprintf("select ID from textfiles where postdate < %s - interval %d day", $db->escapeString($currTime_ori["now"]), $this->site->textfilesretentiondays));
foreach ($result as $row)
$r->delete($row["ID"]);
}
Now I would edit this function so that at first all textfiles are automatically downloaded in a root directory /www/backup and then the script should delete the textfiles with the string $r->delete($row["ID"]);
At the moment I have no idea how I could implement this.
For me it's seems to be impossible to give you an completely answer to your question because leak of informations.
Do you store the whole file-content in database or only the path and filename?
It would help us to see whats the content of "$row" which represents one row from database.
If you just store the filename (and optionally the path) you could use the "copy" (http://php.net/manual/de/function.copy.php) function from php to copy the file to your backup-directory. Please note, you have to ensure that the user who's executing the script or running the web-server have the privileges to write into the directory.
You could add this functionality to class textfiles as as method like makeBackup.
There are few information, but I'll give it a try. If you want to backup the rows before deleting them, you can store them in .txt file in json_encoded form using this piece of code inserted in the FOREACH loop, before delete command:
$myfile = fopen("/www/backup/".$row["ID"].".txt", "w") or die("Unable to open file!");
$txt = json_encode($row);
fwrite($myfile, $txt);
fclose($myfile);
By your approach ..
function delete ($id){
$result = $db->query(sprintf("select * from textfiles where id=$id);
//if you have filepath use copy as SebTM suggested
$path = $row['path']; //assuming path is the column name in ur db
$filename = basename($path); //to get filename
$backup_location = '/www/backup/'.$filename;
copy($path, $backup_location);
//if you have data in db
$content = $row['data'] //assuming data to be backed up to file is in a field 'data'
$backup_location = '/www/backup/file.txt';
file_put_contents($backup_location, $content);
}
But this is not the most optimal approach , you could shift even the initial query into delete function above , and call delete function only once, instead of calling it in a loop ..
Related
I try to delete multiple images from folder and also from database, deleting from database is working fine, problem is with deleting from folder I'm using explode function because I have store multiple images inside one column in database. It just won't delete images from folder.
$query = "DELETE FROM table_gallery WHERE id = $deleteId";
$result = mysqli_query($con, $query);
while($row = mysqli_fetch_assoc($result)) {
$temp = explode(',',$row['images'] );
foreach($temp as $image){
$images[]="uploads/gallery/".trim( str_replace( array('[',']') ,"" ,$image ) );
}
foreach($images as $file) {
// Delete given images
unlink($images);
}
}
You have a few issues going on here,
1) Variable Confusion
The most notable is this:
foreach($images as $file) {
// Delete given images
unlink($images);
}
You are opening the array of $images and then dealing with each element in the array as a string reference ($file), but your unlink() command is calling the array, and you can't do that.
Unlink requires you to give it a filepath string. Not an array.
Fix:
foreach($images as $file) {
// Delete given images
unlink($file);
}
Better:
As an aside, if unlink($file); does not work, then you should check your filepath is correct. Remember the current PHP working directory is the directory the PHP script is in, so you should probably set your deleted image path to being the full server filepath such as:
unlink($_SERVER['DOCUMENT_ROOT']. $file);
To ensure you're certain of the file you're deleting.
foreach($images as $file) {
// Delete given images
// /serverfolder/accountfolder/public_html/uploads/gallery/imagename.jpg
unlink($_SERVER['DOCUMENT_ROOT'].$file);
}
2) Your Safety and Security:
Your variable $deleteId might be safe, but it might not. We can't tell from the code you show but you should be aware that if the $deleteId variable is, for example;
$deleteId = '1 OR id > 1';
// which generates:
$query = "DELETE FROM table_gallery WHERE id = 1 OR id > 1";
This is a security risk for your SQL and will delete all records on your database table (and folder). You should use Prepared Statements to ensure this doesn't ever happen.
3) Logic Confusion
you have a reference call mysqli_fetch_assoc but the DELETE SQL command will not return a result set, instead if it is successful it will simply return true.
Returns false on failure. For successful queries which produce a result set, such as SELECT, SHOW, DESCRIBE or EXPLAIN, mysqli_query() will return a mysqli_result object. For other successful queries, mysqli_query() will return true.
You need to structure your code somewhat differently, loading the images column value BEFORE you delete the row.
So, to restructure your code:
Check variables are safe.
load images column values
cycle through values and delete
Once deletion is confirmed then DELETE SQL.
For example:
$query = "SELECT images FROM table_gallery WHERE id = ".(int)$deleteId;
$result = mysqli_query($con, $query);
$abort = false;
while($row = mysqli_fetch_assoc($result)) {
$temp = explode(',',$row['images'] );
foreach($temp as $image){
$images[]="uploads/gallery/".trim( str_replace( array('[',']') ,"" ,$image ) );
}
foreach($images as $file) {
// Delete given images
if(!unlink($_SERVER['DOCUMENT_ROOT'].$file)){
// Delete failed so abort
$abort = true;
}
}
//
if(!$abort){
// all correct images on disk deleted ok so delete DB row
if(mysqli_query($con, "DELETE FROM table_gallery WHERE id = ".(int)$deleteId)){
// Yay deleted ok!
}
}
}
Closing thought:
You need to learn to read your PHP error logs which will spell out all the above.
I have I have static HTML / JS page without any database (I don't need it). However I start fight with some issue. I need to generate random ID which have to be unique(used once and never ever again).
Stardard MySQL way:
On standard application I will do it with storing all used IDs in database
and when needed new one I will simply
// I generate ID here, let's say it's 123
SELECT COUNT(id) FROM table WHERE id = 123
My solution which may be not the best one:
I am thinking alternative may be some storing in file
// Let's generate ID here, and make it 123 again
$handle = fopen("listOfIDs.txt", "r");
if ($handle) {
$used = false;
while (($line = fgets($handle)) !== false) {
if($line = 123) {
$used = true;
break;
}
}
fclose($handle);
return $used;
} else {
// error opening the file.
}
Dispite the fact I can imagine my option may work it could be super slow when file become bigger.
Question:
What's the best way to keep simple unique IDs without using database.
Edit:
I forgot to mentioned that unique ID have to be numbers only.
You could use uniqid(), str_rand(something), timestamp, some hash with random data that you probably never get twice.
Or, doing your way, you could have a single line with information in this file, just the last used id:
$fp = fopen("lastID.txt", "r+");
if (flock($fp, LOCK_EX)) { // lock the file
$lastId = fgets($fp); // get last id
$newId = $lastId +1; //update the id
ftruncate($fp, 0); // truncate file
fwrite($fp, $newId); //write the new Id
fflush($fp); // flush output
flock($fp, LOCK_UN); // release the lock
} else {
throw new Exception("Could not get the lock");
}
fclose($fp);
return $newId;
Maybe you can use a mix of the current timestamp, the request ip, and a randomnumber:
$unique = microtime().$_SERVER['REMOTE_HOST'].rand(0,9999);
Sure theorically you can get a request that executes this operation in the same microtime, with the same remote host, and matching the random number, but it's almost impossible, I think.
You can use PHP uniqid with $more_entropy = true, which increases the likelihood that the result will be unique.
$id = uniqid("", true);
You can also work some random number out using current date and time, etc. You should consider how fast the users may generate these numbers, if it's super fast, there might be a possibility of two different users generating the same $id because it happened at the same time.
I am trying to create a TXT file with PHP. This works fine. Unfortunately, it seems that I do not have the correct syntax, because there is no content inserted using the file_put_contents function to put the data from my SQLite table into the TXT file.
<?php
$db = new SQLite3('sshTunnel.sqlite');
$results = $db->query('SELECT * FROM mydata');
$file = 'D:\test.txt';
file_put_contents($file, $results);
?>
The file is written, but it contains 0 Bytes.
If there are rows, $results will contain an SQLite3Result object. You still need to loop over the result set to get the data.
For example:
while ($row = $results->fetchArray()) {
file_put_contents($file, implode(', ', $row), FILE_APPEND);
}
Note that this is just an example, there are dedicated functions to write CSV if you need that.
try output buffering:
ob_start() ;
var_dump($results) ;
file_put_contents($file, ob_get_clean()) ;
I am in need to create a CSV file getting the data from a mySQL DB.
The fact is that I want the CSV tp be corrected labeled and not just writing the data like this:
id,name,url
1,thisismyname,thisismyurl
I need the CSV file to look well ordered and each data inserted in the relative column.
Also with the function I am going to add below I can only grab the data from the DB and write it to the CSV file as it is. But I need to work with the data and have the CSV labeled in this way:
Campaign Name:
Name of the campaign
Campaign Url:
Url of the campaign
Tot visits:
Tot of visits
Tot unique visits:
Tot of unique visits
id name url
1 thisname this url
2 thisname this url
3 thisname this url
4 thisname this url
5 thisname this url
This is the PHP code I have so far..I need to understand how to achieve a correct structure of the CSV with PHP and adding the lines in it the exact way I want..
Thanks for your help!
function genCSV($filename, $attachment = true, $headers = true) {
// send response headers to the browser
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=' . $filename);
$fp = fopen('php://output', 'w');
$query = "SELECT * FROM campaigns";
$result = mysql_query($query) or die(mysql_error());
if ($headers) {
// output header row (if at least one row exists)
$row = mysql_fetch_assoc($result);
if ($row) {
fputcsv($fp, array_keys($row));
// reset pointer back to beginning
mysql_data_seek($result, 0);
}
}
while ($row = mysql_fetch_assoc($result)) {
fputcsv($fp, $row);
}
fclose($fp);
}
Here is a much less elegant solution than the one proposed by #Tom Regner.
I needed to backup certain database tables (all those with a given prefix) but not others. This method, though somewhat slow, allows you to select exactly which tables and which columns from those tables are copied. It was originally written to allow each piece of data to be AES encrypted before being entered into the file but there are other uses for it. As written here, the result is a CSV file with the first line containing the list of columns for the table and the rest containing the data in CSV. It will stand adaptation to output the result of any sql into CSV, if you like.
Obviously: mysqlidb = mysqli databse resource, backups/ = directory to put finished files in.
FWIIW, here is the code:
$sql="SHOW TABLES LIKE 'yourtable%'";
$result = $mysqlidb->query($sql);
$tableresult=$mysqlidb->query($sql);
while($tables=$tableresult->fetch_assoc())
{
$keys=array_keys($tables);
$tablename=$tables[$keys[0]];
echo "Writing $tablename <BR>";
$file=fopen("backups/$tablename.enc","w");
$cols=array();
$sql="SHOW COLUMNS FROM $tablename";
$result=$mysqlidb->query($sql);
while($row=$result->fetch_assoc())
{
$cols[]=$row['Field'];
}
fputcsv($file,$cols);
$sql="SELECT * FROM $tablename";
$result=$mysqlidb->query($sql);
while($row=$result->fetch_assoc())
{
fputcsv($file,$row);
}
fclose($file);
}
I have a mysql blob field in which our team stored an image for every record. Now I want to download all images on my hard disk through php script. A prompt response will be appreciated.
Best Regards...
Aisha
$result=mysql_query("SELECT * FROM test WHERE 1");
while($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$filename = rand(1, 100).'.txt';
file_put_contents('./'.$filename, $row['blob']);
}
This is working (tested).
It wil save the file under a random filename (1-100.txt).
You can change the filename by changing $filename.
And here is a simple sample MySQL-table with 2 demo files with content Test #1 and Test #2:
CREATE TABLE IF NOT EXISTS `test` (`blob` blob NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `test` (`blob`) VALUES(0x5468697320697320746573742023312e), (0x5468697320697320546573742023322e);
you can use file_put_contents,
fetch rows from your database and foreach row write blob/data to file
Error in Writing to Image file from PHP
http://php.net/manual/en/function.file-put-contents.php
You can try this also........
function save_file($file_id, $target_folder) {
$result = $DB->get_file($file_id);
$file_content = $result->fields['your_file_content_field'];
$name = $result->fields['name'];
/* Decode only if the file contents base64 encoded
* before inserting to database.
*/
$file_content = base64_decode($file_content);
return file_put_contents($target_folder.'/'.$name, $file_content);
}