Check if file copy was successful - php

After running the command copy($uploadedFile, "pdf/".$fullFileName);, what would be the quickest and most efficient way to verify that the file copied successfully?

This would be enough no?
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
}
ref: http://php.net/manual/en/function.copy.php

If you look at the copy function in the PHP documentation, you'll see:
Returns TRUE on success or FALSE on failure.
So, something as simple as:
if(!copy($uploadedFile, "pdf/".$fullFileName)) {
// Failure code
}
Or:
$returnCode = copy($uploadedFile, "pdf/".$fullFileName);
if(!$returnCode) {
// Failure code
}
would be sufficient.

You can compare size whlist copying - if sizes equals we can assume copying is done..
$fs1=$fs='';
$filename = 'test.zip'; // copy from ftp or slow copy..
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<25; $i++){
echo "<hr> Compare \n";
echo "<br>fs1: $fs1";
$fs='';
$fs = filesize($filename);
echo "<br>fs: $fs";
if ( $i > 0 )
if ( $fs1 === $fs ) break;
$fs1 = $fs;
ob_flush();
flush();
sleep(2);
clearstatcache();
}
echo "<br>Done copying.";
ob_end_flush();

Related

PHP Script ,php://input check for empty File

Hello i need help with my PHP script.
The Upload function works great, but many files are empty.
Can you help me please to check first IF file is empty or < 1 byte. and Ignore them.
<?php
$vist_page = "post2.php";
include "logger.php";
file_put_contents("outputfile.txt".uniqid(), file_get_contents("php://input"));
?>
Thanks ;)
One way to do that would be to use strlen() to check the length of the string, which could be done by replacing
file_put_contents("outputfile.txt".uniqid(), file_get_contents("php://input"));
with
$content = file_get_contents("php://input");
if (strlen($content)) {
file_put_contents("outputfile.txt".uniqid(), $content);
}
else {
// Your error response here
}
$filename = 'somefile.txt';
if (filesize($filename) < 1) {
//ignore
} else {
//do stuff here
}
filesize returns the file size in bytes
https://www.php.net/manual/en/function.filesize.php
this may be more effecient:
$filename = 'somefile.txt';
if (filesize($filename) > 0) {
//do stuff here
}

Tail -f live output process still running

I am trying to do a live output of a file called fail2ban.log this log is on my linux server and i try to proccess it using. The tail process stay opened so it uses loads of cpu performance after some pepoles open the page since the process stay opened
I tried some solution of killing it with
while(true)
{
if($flag === false) die(); // Or exit if you prefer
}
The server is on Apache2
My code :
<?php
echo "Number of banned ip (live) : ";
$hand = popen("grep 'Ban' /var/log/fail2ban.log | wc -l 2>&1", 'r');
while(!feof($hand)) {
$buff = fgets($hand);
echo "$buff<br/>\n";
ob_flush();
flush();
}
pclose($hand);
echo " ";
echo "Current Log (go at the bottom of the page for the live log)";
echo " ";
$output = shell_exec('cat /var/log/fail2ban.log 2>&1');
echo "<pre>$output</pre>";
echo "Live Logs";
echo "<h1> </h1> ";
echo " ";
$handle = popen("tail -f /var/log/fail2ban.log 2>&1", 'r');
while(!feof($handle)) {
$buffer = fgets($handle);
echo "$buffer<br/>\n";
ob_flush();
flush();
}
pclose($handle);
?>
I want it to kill the process when the user quit the page.
No #jhnc In this case, popen is guilty, which does not end the process when the program is closed.
In general, PHP is one of the worst choices to implement tail -f. It's better to use node + websocket.
In this case, you need to check if something has been added to the file by another method. From http://php.net/manual/en/function.inotify-init.php#101093
<?php
/**
* Tail a file (UNIX only!)
* Watch a file for changes using inotify and return the changed data
*
* #param string $file - filename of the file to be watched
* #param integer $pos - actual position in the file
* #return string
*/
function tail($file,&$pos) {
// get the size of the file
if(!$pos) $pos = filesize($file);
// Open an inotify instance
$fd = inotify_init();
// Watch $file for changes.
$watch_descriptor = inotify_add_watch($fd, $file, IN_ALL_EVENTS);
// Loop forever (breaks are below)
while (true) {
// Read events (inotify_read is blocking!)
$events = inotify_read($fd);
// Loop though the events which occured
foreach ($events as $event=>$evdetails) {
// React on the event type
switch (true) {
// File was modified
case ($evdetails['mask'] & IN_MODIFY):
// Stop watching $file for changes
inotify_rm_watch($fd, $watch_descriptor);
// Close the inotify instance
fclose($fd);
// open the file
$fp = fopen($file,'r');
if (!$fp) return false;
// seek to the last EOF position
fseek($fp,$pos);
// read until EOF
while (!feof($fp)) {
$buf .= fread($fp,8192);
}
// save the new EOF to $pos
$pos = ftell($fp); // (remember: $pos is called by reference)
// close the file pointer
fclose($fp);
// return the new data and leave the function
return $buf;
// be a nice guy and program good code ;-)
break;
// File was moved or deleted
case ($evdetails['mask'] & IN_MOVE):
case ($evdetails['mask'] & IN_MOVE_SELF):
case ($evdetails['mask'] & IN_DELETE):
case ($evdetails['mask'] & IN_DELETE_SELF):
// Stop watching $file for changes
inotify_rm_watch($fd, $watch_descriptor);
// Close the inotify instance
fclose($fd);
// Return a failure
return false;
break;
}
}
}
}
// Use it like that:
$lastpos = 0;
$file = '/var/log/fail2ban.log'l
while (true) {
echo tail($file,$lastpos);
ob_flush();
flush();
}
?>
And you can't forget about max_execution_time and Apache limits

Execute the scripts at the same time if-else problem

I can't use flock at the moment(server restrictions) so I am creating a alternative file lock system. Here is my code.
$dir = "C:\\wamp\\www\\test\\";
$files = scandir($dir);
for($i=0; $i<count($files); $i++)
{
if(substr(strrchr($files[$i],'.csv'),-4) == '.csv')
{
echo "File ".$files[$i]." is a csv"."</br>";
if (file_exists("$dir$files[$i].lock"))
{
echo $files[$i]." has lock in place"."</br>";
$i++;
}
else
{
if($file_handle = fopen("$dir$files[$i]", "rb"))
{
$file_lock_handle = fopen("$dir$files[$i].lock", "w");
echo "Setting Lock"."</br>";
//Do Logic
fclose($file_handle);
fclose($file_lock_handle);
sleep(3);
unlink("$dir$files[$i].lock");
}
}
}
else
{
//Do nothing
}
}
If I run these scripts side by side. It waits for the first script to be finished before it executes the second one. How can I run them concurrently? i.e. If a lock exists I want it to skip that file and go the the next one.
There is a good example of this here: http://www.php.net/manual/en/function.flock.php#92731

PHP: How to read a file live that is constantly being written to

I want to read a log file that is constantly being written to. It resides on the same server as the application. The catch is the file gets written to every few seconds, and I basically want to tail the file on the application in real-time.
Is this possible?
You need to loop with sleep:
$file='/home/user/youfile.txt';
$lastpos = 0;
while (true) {
usleep(300000); //0.3 s
clearstatcache(false, $file);
$len = filesize($file);
if ($len < $lastpos) {
//file deleted or reset
$lastpos = $len;
}
elseif ($len > $lastpos) {
$f = fopen($file, "rb");
if ($f === false)
die();
fseek($f, $lastpos);
while (!feof($f)) {
$buffer = fread($f, 4096);
echo $buffer;
flush();
}
$lastpos = ftell($f);
fclose($f);
}
}
(tested.. it works)
Yes, you need to sleep some time in the loop but you don't have to reopen the file. I was just looking for a similar problem. I wanted to read a file that might have been changed since last read.
The problem is that the resource has reached end of file (EOF). And does not continue to read. The solution is to reset the pointer with fseek($fh, ftell($fh)).
A complete program that waits for input in a text file might look like this one:
<?php
$fh = fopen('/var/log/system', 'r');
while (true) {
$line = fgets($fh);
if ($line !== false) {
// show the line or send it via email or to a websocket..
} else {
// sleep for 0.1 seconds (or more?)
usleep(0.1 * 1000000);
fseek($fh, ftell($fh));
}
}
For example :
$log_file = '/tmp/test/log_file.log';
$f = fopen($log_file, 'a+');
$fr = fopen($log_file, 'r' );
for ( $i = 1; $i < 10; $i++ )
{
fprintf($f, "Line: %u\n", $i);
sleep(2);
echo fread($fr, 1024) . "\n";
}
fclose($fr);
fclose($f);
//Or if you want use tail
$f = fopen($log_file, 'a+');
for ( $i = 1; $i < 10; $i++ )
{
fprintf($f, "Line: %u\n", $i);
sleep(2);
$result = array();
exec( 'tail -n 1 ' . $log_file, $result );
echo "\n".$result[0];
}
fclose($f);
you can close the file handle when it is not used(once a portion of data has been written). or you can use a buffer to store the data and put it to the file only when it's full. this way you won't have the file open all the time.
if you want to get everything that is written to the file as soon as it is written there, you might need to extend the code, writing the data, so that it would output to other places too(screen, some variable, other file...)
<?php
$fp = fopen('/var/log/syslog', 'r');// Read only
while (true) {
$line = stream_get_line($fp, 1024 * 1024, "\n");// Full line found ? (searches for a line break)
if ($line === false) {
usleep(100000);// 100ms
continue;
}
echo 'line:' . $line . PHP_EOL;
}
// -- Code impossible to reach --
// fclose($fp);
Just an idea..
Did you think of using the *nix tail command? execute the command from php (with a param that will return a certain number of lines) and process the results in your php script.

How To watch a file write in PHP?

I want to make movement such as the tail command with PHP,
but how may watch append to the file?
I don't believe that there's some magical way to do it. You just have to continuously poll the file size and output any new data. This is actually quite easy, and the only real thing to watch out for is that file sizes and other stat data is cached in php. The solution to this is to call clearstatcache() before outputting any data.
Here's a quick sample, that doesn't include any error handling:
function follow($file)
{
$size = 0;
while (true) {
clearstatcache();
$currentSize = filesize($file);
if ($size == $currentSize) {
usleep(100);
continue;
}
$fh = fopen($file, "r");
fseek($fh, $size);
while ($d = fgets($fh)) {
echo $d;
}
fclose($fh);
$size = $currentSize;
}
}
follow("file.txt");
$handle = popen("tail -f /var/log/your_file.log 2>&1", 'r');
while(!feof($handle)) {
$buffer = fgets($handle);
echo "$buffer\n";
flush();
}
pclose($handle);
Checkout php-tail on Google code. It's a 2 file implementation with PHP and Javascript and it has very little overhead in my testing.
It even supports filtering with a grep keyword (useful for ffmpeg which spits out frame rate etc every second).
$handler = fopen('somefile.txt', 'r');
// move you at the end of file
fseek($handler, filesize( ));
// move you at the begining of file
fseek($handler, 0);
And probably you will want to consider a use of stream_get_line
Instead of polling filesize you regular checking the file modification time: filemtime
Below is what I adapted from above. Call it periodically with an ajax call and append to your 'holder' (textarea)... Hope this helps... thank you to all of you who contribute to stackoverflow and other such forums!
/* Used by the programming module to output debug.txt */
session_start();
$_SESSION['tailSize'] = filesize("./debugLog.txt");
if($_SESSION['tailPrevSize'] == '' || $_SESSION['tailPrevSize'] > $_SESSION['tailSize'])
{
$_SESSION['tailPrevSize'] = $_SESSION['tailSize'];
}
$tailDiff = $_SESSION['tailSize'] - $_SESSION['tailPrevSize'];
$_SESSION['tailPrevSize'] = $_SESSION['tailSize'];
/* Include your own security checks (valid user, etc) if required here */
if(!$valid_user) {
echo "Invalid system mode for this page.";
}
$handle = popen("tail -c ".$tailDiff." ./debugLog.txt 2>&1", 'r');
while(!feof($handle)) {
$buffer = fgets($handle);
echo "$buffer";
flush();
}
pclose($handle);

Categories