I have a .bat file that encodes an mp3 file on the server side, and I also have a php function that checks if the file exists, and then adds it as an HTML list item. The problem I'm running into - sometimes the mp3 file isn't done encoding on the server side. If somebody were to try downloading the file while it's in the process of encoding it will crash the browser.
Can I check to make sure the filesize is finished increasing before listing the item?
Here's the function that checks if the file exists:
function ListDir($dir_handle,$path) {
global $listing;
echo "<ul>";
while (false !== ($file = readdir($dir_handle))) {
$dir =$path . $file;
if(is_dir($dir) && $file != '.' && $file !='..' && filesize($file) {
$handle = #opendir($dir) or die("Unable to open file $file");
echo "<li>".$dir;
ListDir($handle, $dir);
echo "</li>";
} elseif($file != '.' && $file !='..' && $file !='.htaccess') {
$new_string = ereg_replace("[^A-Za-z.]", "", $file);
echo '<li>'.str_replace('wav', 'mp3', $new_string).'</li>';
}
}
echo "</ul>";
closedir($dir_handle);
}
Have the bat encode, then move to a final location for a "finished" state, if it doesn't exist there - it's not done. This is similar to drew010's answer except it utilizes the same file, from a working directory to a production directory.
This also prevents it being accessible by any resources until it's ready which could potentially cause problems.
You can't really know the final filesize, so have your bat file create a file like mp3filename.work or something and then have the bat file delete it when the encoding finishes, so if the .work file doesn't exist, then the encoding is done.
Related
I'm trying to create a script that will send across files from one server to another. My script successfully does that as well as checks if the file has something in it or not. My next step is to check whether the file already exists on the server; if the file already exists it does not send and if it does not exist, it does send.
I've tried a few different things and can't seem to get my head around it. How can I get it to check whether the file already exists or not? Any help would be appreciated!
(I had a look at some similar questions but couldn't find anything specific to my issue.)
require('constants.php');
$files = $sftp->nlist('out/');
foreach($files as $file) {
if(basename((string) $file)) {
if(strpos($file,".") > 1) { //Checks if file
$filesize = $sftp->size('out/'.$file); //gets filesize
if($filesize > 1){
if (file_exists('import/'.$file)){
echo $file.' already exists';
}
else {
$sftp->get('out/'.$file, 'import/'.$file); //Sends file over
//$sftp->delete('out/'.$file); //Deletes file from out folder
}
else {
echo $file. ' is empty.</br>';
}
}
}
}
}
EDIT: To try and get this to work, I wrote the following if statement to see if it was finding the file test.php;
if (file_exists('test.txt')){
echo 'True';
} else {
echo 'False';
}
This returned true (a good start) but as soon as I put this into my code, I just get a 500 Internal Server Error (extremely unhelpful). I cannot turn on errors as it is on a server that multiple people use.
I also tried changing the file_exists line to;
if (file_exists('test.txt'))
in the hopes that would work but still didn't work.
Just to clarify, I'm sending the files from the remote server to my local server.
There is a closing curly brace missing right before the second else keyword.
Please try to use a code editor with proper syntax highlighting and code formatting to spot such mistakes on the fly while you are still editing the PHP file.
The corrected and formatted code:
require('constants.php');
$files = $sftp->nlist('out/');
foreach ($files as $file) {
if (basename((string)$file)) {
if (strpos($file, ".") > 1) { //Checks if file
$filesize = $sftp->size('out/' . $file); //gets filesize
if ($filesize > 1) {
if (file_exists('import/' . $file)) {
echo $file . ' already exists';
} else {
$sftp->get('out/' . $file, 'import/' . $file); //Sends file over
}
} else {
echo $file . ' is empty.</br>';
}
}
}
}
Your code checks the file exist in your local server not in remote server.
if (file_exists('import/'.$file)){
echo $file.' already exists';
}
You need to check in remote server using sftp object like
if($sftp->file_exists('import/'.$file)){
echo $file.' already exists';
}
Edit:
Add clearstatcache() before checking file_exists() function as the results of the function get cached.
Refer: file_exists
I inherited a piece of code that has suddenly stopped working. I've isolated the code down to it appears this function is no longer reading the directory and locating the xml file found in it for later processing. I've uploaded versions of the xml file with uppercase and lowercase .xml/.XML extension with the same result: NO XML FILE FOUND
I've verified that the print_r is in fact reading the correct directory where the xml file resides. There are other files in the directory but that has been the case for years. Did something change recently in PHP to stop this code from working?
function GetXMLFile($path) {
$path .= "/";
print_r($path);
$filename = "";
if ($handle = opendir($path)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if (GetFileExtention($path . strtolower($file)) =="XML") {
$filename = $file;
}
}
}
closedir($handle);
}
return $filename;
}
Later in the code the function is called that is producing the NO XML error. I've confirmed the $config['xml_dir'] variable below matches the print_r directory location above as well.
$cur_xml_file = GetXMLFile($config['xml_dir']);
if ($cur_xml_file == "") {
echo "NO XML FILE FOUND";
exit(0);
}
No, nothing has changed in PHP recently that would cause the code you show to stop functioning. If it doesn't work anymore, the error is somewhere else.
Then again, that's a lot of code to find a file. Why don't you just do change it to
function GetXMLFile($path) {
$all_xml_files = glob("$path/*.{xml,XML}", GLOB_BRACE);
return !empty($all_xml_files) ? realpath($all_xml_files[0]) : "";
}
That will return the absolute path of the first file with an .XML or .xml extension in the given $path or an empty string if no files are found or an error occured.
See if the error goes away when you change it to that.
I have code which generates a text file on my server. I then need this file uploaded to another server using sftp. To start things off, I do
if(performLdapOperations()) {
sleep(10);
performFtpOperation();
}
performLdapOperations produces the text file and places it on my server, performFtpOperation takes this text file and uploads to another server. This is my function
function performFtpOperation() {
global $config;
$local_directory = getcwd() .'/outputs/';
$remote_directory = '/home/newfolder/';
$sftp = new SFTP($config::FTP_SERVER, 22, 10);
if (!$sftp->login($config::FTP_USER, $config::FTP_PASSWORD)) {
exit('Login Failed');
}
$files_to_upload = array();
/* Open the local directory form where you want to upload the files */
if ($handle = opendir($local_directory))
{
/* This is the correct way to loop over the directory. */
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
$files_to_upload[] = $file;
}
}
closedir($handle);
}
if(!empty($files_to_upload))
{
/* Now upload all the files to the remote server */
foreach($files_to_upload as $file)
{
$success = $sftp->put($remote_directory . $file,
$local_directory . $file,
NET_SFTP_LOCAL_FILE);
}
}
}
So the text file that is produces is in my outputs folder. I then want to take this file and upload to a new server to the location /home/newfolder/
Everything seems to work, and the file seems to get uploaded to the new server. However, when I open the file that has been uploaded, all it contains is the path of where the file is, nothing else. The file on my server which is in the outputs folder contains everything, for some reason something is going wrong when sending it over sftp?
Is there anything in my code that may be causing this?
Thanks
It looks like you're using the 2.0 version of phpseclib, which is namespaced. If that's the case then the problem is with this line:
$success = $sftp->put($remote_directory . $file,
$local_directory . $file,
NET_SFTP_LOCAL_FILE);
Try this:
$success = $sftp->put($remote_directory . $file,
$local_directory . $file,
SFTP::SOURCE_LOCAL_FILE);
When I trying to open my zip file which is generated by PHP Zip Archive, there is an alert showing
"Windows cannot open the folder. The Compressed (zipped) Folder
'filename' is invalid." error opening in Windows Explorer.
But I can open the file through 7-zip. In some reason, I have to ensure the zip file can open by Windows Explorer. Is there any problem when I generated the zip file? Please help!
function create_a_zip($files = array(),$dest = '',$root_folder,$overwrite = false) {
if(file_exists($dest) && !$overwrite) {
return false;
}
$valid_files = array();
if(is_array($files)) {
foreach($files as $file) {
if(file_exists($file)) {
$valid_files[] = $file;
}
}
}
if(count($valid_files)) {
$zip = new ZipArchive();
if($zip->open($dest,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
foreach($valid_files as $valid_file) {
if(is_dir($valid_file) === true){
foreach(glob($valid_file . '/*') as $file){
$zip->addFile($file, $root_folder . $file);
}
}else if (is_file($valid_file) === true){
$zip->addFile($valid_file, $root_folder . $valid_file);
}
}
$zip->close();
return file_exists($dest);
}
else
{
return false;
}
}
For me, the solution was to use ob_end_clean() before outputting zip file contents (as noted by #Ywis in the comments)...
ob_end_clean();
readfile($zipfilename); // outputs zip file's content
... even if you don't output any characters before that.
I think the problem originates from:
$zip->addFile($file,$file);
Unless you have your php script in the same directory as the files you want to add to zip, you will need to include the file path. The 2nd parameter in addFile is the name of the file inside the zip, so if your $file var includes the path, that’s where the issue probably coming from. Try to change the code to :
$filenameonly = preg_replace("/(.*)\/?([^\/]+)/","$2",$file);
$zip->addFile($file,$filenameonly );
which will strip out the file path (if any) and leave you only the file name for the 2nd variable in addFile.
If this will solve your problem you will know for sure that the problem was in your filenames and can pinpoint it easily.
Just send as parameter to absolute path for example $abspath. Then use it in
$filenameonly = str_replace($abspath,"",$file);
$zip->addFile($file, $filenameonly);
It works 100% even in Window 8 and even your files you zip are in folders.
Instead of using str_replace string function, you can use built-in file-system functions.
$zip->addFile(realpath($file), pathinfo($file, PATHINFO_BASENAME));
Windows zip does not recognize paths begining with "/"
Just remove the first "/" in the filepath.
Like this:
if ( substr($root_folder,0,1) == '/' ) {
$root_folder = substr($root_folder,1);
}
$zip->addFile($file, $root_folder . $file);
I have these files in /public_html/ directory :
0832.php
1481.php
2853.php
3471.php
index.php
and I want to move all those XXXX.php (always in 4 digits format) to directory /tmp/, except index.php. how to do it with reg-ex and loop?
Alternatively, how about moving all files (including index.php) first to /tmp/ then later on put only index.php back to /public_html/, which one you think is less CPU consuming?
Last thing, I found this tutorial to move file using PHP: http://www.kavoir.com/2009/04/php-copying-renaming-and-moving-a-file.html
But how to move ALL files in a directory?
You can use FilesystemIterator with RegexIterator
$source = "FULL PATH TO public_html";
$destination = "FULL PATH TO public_html/tmp";
$di = new FilesystemIterator($source, FilesystemIterator::SKIP_DOTS);
$regex = new RegexIterator($di, '/\d{4}\.php$/i');
foreach ( $regex as $file ) {
rename($file, $destination . DIRECTORY_SEPARATOR . $file->getFileName());
}
The best way would be to do it directly via the file system, but if you absolutely have to do it with PHP, something like this should do what you want - you'll have to change the paths so that they are correct, obviously. Note that this assumes that there could be other files in the public_html directory, and so it only get the filenames with 4 numbers.
$d = dir("public_html");
while (false !== ($entry = $d->read())) {
if($entry == '.' || $entry == '..') continue;
if(preg_match("#^\d{4}$#", basename($entry, ".php")) {
// move the file
rename("public_html/".$entry, "/tmp/".$entry));
}
}
$d->close();
in fact - I went to readdir manual page and the fist comment to read is:
loop through folders and sub folders with option to remove specific files.
<?php
function listFolderFiles($dir,$exclude){
$ffs = scandir($dir);
echo '<ul class="ulli">';
foreach($ffs as $ff){
if(is_array($exclude) and !in_array($ff,$exclude)){
if($ff != '.' && $ff != '..'){
if(!is_dir($dir.'/'.$ff)){
echo '<li>'.$ff.'';
} else {
echo '<li>'.$ff;
}
if(is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff,$exclude);
echo '</li>';
}
}
}
echo '</ul>';
}
listFolderFiles('.',array('index.php','edit_page.php'));
?>
Regexes are in fact overkill for this, as we only need to do some simple string matching:
$dir = 'the_directory/';
$handle = opendir($dir) or die("Problem opening the directory");
while ($filename = readdir($handle) !== false)
{
//if ($filename != 'index.php' && substr($filename, -3) == '.php')
// I originally thought you only wanted to move php files, but upon
// rereading I think it's not what you really want
// If you don't want to move non-php files, use the line above,
// otherwise the line below
if ($filename != 'index.php')
{
rename($dir . $filename, '/tmp/' . $filename);
}
}
Then for the question:
alternatively, how about moving all files (including index.php) first to /tmp/ then later on put only index.php back to /public_html/, which one you think is less CPU consuming?
It could be done, and it would probably be slightly easier on your CPU. However, there are several reasons why this doesn't matter. First off, you're already doing this in a very inefficient way by doing it through PHP, so you shouldn't really be looking at the strain this puts on your CPU at this point unless you are willing to do it outside PHP. Secondly, that would cause more disk access (especially if the source and destination directory aren't on the same disk or partition) and disk access is much, much slower than your CPU.