I have a PHP code that connects to a FTP server, reads a file's content, makes a minor change, and than overrides the original file.
it looks like:
$stream_context = stream_context_create(array('ftp' => array('overwrite' => true)));
$file_content = file_get_contents($ftp_file); // this line works
$file_content = str_replace('some content', 'another content', $file_content); // this also..
file_put_contents($ftp_file, $file_content, 0, $stream_context); // this one doesn't :/
the real issue is that the "file_put_contents" worked for a long time, but now it doesn't.
what it does now is weird: it deletes the original file from the server..
also, if i'm changing it to something like:
file_put_contents($new_ftp_file, $file_content);
from what I know, it should create the new file and put the content in it, but it doesn't create it at all.
the hosting service i'm using has a PHP version change a few days ago. I don't remember the what the previous version was, but the current is: 5.2.17
thanks! :)
some changes
I found this piece: http://www.php.net/manual/en/function.file-put-contents.php#86864
doting the same as "file_put_contents" but with foen, fwrite and fclose (I send his example because of the results..). his functions is returning "false" if it couldn't to "fopen" the file, or the "bytes" if it succeeded. I got "false" :/
which means it couldn't even do the:
#fopen($filename, 'w');
although the "file_get_contents" with the same file address is working.
reading is working (but if you take the $filename and use it yourself on a client FTP - it works):
#fopen($filename, 'r');
the "open base_dir" for my hosting (which makes the action) is set to false, but the target hosting (which has the target-file) is set to be true.
I had an idea to save the new content on a new file, so I tried something like:
$f = #fopen($new_ftp_file, 'w'); //this one seems to work and connect
fwrite($f, $file_content); // this one seems to work either and returning the number of byes..
fclose($f);
the problem is that none of them really works. I logged in to the FTP address, using the same credentials that my script is using, and I haven't found the new file. It wasn't created at all. (as I remind you, "$new_ftp_file" is a path to a file that doesn't exists, so "w" mode on "fopen" should create it).
file_put_contents do erase the file by default if it already exists. You have to ask him to don't.
Look at here:
http://www.php.net/manual/en/function.file-put-contents.php
See: If filename does not exist, the file is created. Otherwise, the existing file is overwritten, unless the FILE_APPEND flag is set.
this is not the best solution (definitely), but I managed to figure something..
I used 2 different hosts on them same hosting service, both of the having "open base_dir = On" & "safe mode = Off".
it looks something like:
$ftpstring = "ftp://user:password#anotherhosteddomain.com";
$file = file_get_contents($ftpstring . 'index.html'); // this line works as expected. (yeah, the other hosting has this file);
and then, if you're trying to write something like:
$handler = fopen($ftpstring.'index.html', "w");
it wouldn't work, and tell you it cannot access on writing mode to an existing file.
so if you're doing something like:
$newfile_handler = fopen($ftpstring.'index_new_version.html', "w");
fwrite($newfile, "1122");
so yeah - it works!
but now is a tricky issue.. when i'm adding this line:
fclose($newfile_handler);
the new file is deleted from the hosting!!
I couldn't find any reason why "fclose" is deleting the file after it was create at "fopen" and written in at "fwrite".
so if you're not adding the "fclose" line - it works, but it doesn't close the connection, and also I have to actually delete the existing file before I can override it with a new content, which makes it silly..
although it works, I would really like someone to give me a better solution than mine.
Related
All I am attempting to do is append to a file, and then read the file. In this case, I am appending 'hi', so my results look like 'hi', 'hihi', 'hihihi', etc. This works. What is so baffling is that if I then look at my temp dir, I see no file /tmp/bb.txt. How am I able to append to a file I cannot find in my file system? Am I under some sort of fake root or something?
$content is becoming a longer string each time, so it must be saving somewhere. When I step through, $x is true.
public function testFileAction()
{
$file = '/tmp/bb.txt';
$x = file_exists($file);
$mf = fopen($file, 'a');
fwrite($mf, 'hi');
fclose($mf);
$mfr = fopen($file, 'r');
$content = fread($mfr, filesize($file));
fclose($mfr);
echo $content;
}
Code is correct.
How are you running this? File can be owned by user used by server (apache for example).
You (user in the terminal) probably don't have permission to read the file.
Try sudo ls /tmp.
The problem is that '/tmp' might not mean the actual path of '/tmp' to php. Linux can be configured in a way that each process has its own tmp directory that it uses separately from any other process.
https://blog.oddbit.com/post/2012-11-05-fedora-private-tmp/
Here is a snippet of what I'm trying to do:
$file = fopen($path, "wb");
fwrite($file, $data);
fclose($file);
Simple enough.
But when I open the created file, I see 0x0D inserted before 0x0A everywhere. I understand that this will happen if I open the file without binary mode.
But I've clearly specified I want binary mode. Maybe my brain isn't functioning right or something, so.. Anyone got a solution?
It turns out, for some weird reason, the problem was with my $path. My $path value was "temp".
It would generate the file named "temp" but would refuse to open it in binary mode. Giving the file an extension like "temp.bin" or "temp.tmp" allowed it to work in binary mode.
Problem solved for now but I'm still wondering why it works like this.
Seems the problem is with the $path. Please make sure you have given the correct file path.
If you are defining the $path with a dynamic file name, use / before the file name. For example, $var = "/var/www/html/projectFolder/folderFile/". "Filename.fileformat"
If you're working with URLs in a redirection context, then the root directory ('/') refers to your domain's root. The same goes for paths for linking files or images and for include and require directives.
You're making the classic mistake of confusing data with the representation of that data.
Let's say you have a text file. If you open it in Notepad, you'll see the following:
$str = "Hello world!";
echo bin2hex($str); // output: 48656c6c6f20776f726c6421
$file = fopen($path, "wb");
$data = bin2hex($data);
fwrite($file, $data);
fclose($file);
I'm writing a function in php, client side I have a canvas image which I use toDataUrl() along with a file name to save the image on the server. The here's the code:
<?php
$imageData=$GLOBALS['HTTP_RAW_POST_DATA'];
$data = json_decode($imageData, true);
$file = $data["file"];
$image = $data["data"];
$filteredData=substr($image, strpos($image, ",")+1);
$unencodedData=base64_decode($filteredData);
$fp = fopen( 'image/' . $file , 'wb' );
fwrite( $fp, $unencodedData);
fclose( $fp );
?>
The thing is that this code works. And for two out of three of the pages I used it on it works fine. The problem is when I copy and pasted it a third time to implement it again, for some reason the file is made on the server except that no data get's written into the file. I don't think it's a problem client side because I write in a debug alert message in the javascript and a debug echo into the PHP and both are able to print out the data fine. I made this short debug file:
<?php
$fp = fopen('data.txt', 'wb');
if(is_writable('data.txt')){
echo "file is writable<br>";
}
if(fwrite($fp, 'test') == FALSE){
echo "failed to write data<br>";
}
fclose($fp);
?>
And the output is
file is writable
failed to write data
I've tried using chmod and setting everything, the folder, the text file before I write to it to 0777 and I still get the same result; the file is made but no data is written into it. Is there anything I'm missing or any other approaches that might help. I haven't found anything on google and am still baffled as to why the same code worked exactly as expected twice before suddenly stopping for no apparent reason.
Thanks in advance.
I know this is an old post, but I had a very similar problem and found a solution (for me at least)! I ran out of disk space on my server, so it could create a 0 byte file, but wouldn't write to it. After I cleared out some space (deleted a 13gb error.log file) everything started working again as expected.
If fopen works but fwrite mysteriously doesn't, check your disk space. 'df -h' is the command to check disk space on a linux server.
instead of $fp = fopen('data.txt', 'wb'); give $fp = fopen('data.txt', 'w'); and try
Changed "wb" to "w"
When you write $fp = fopen('data.txt', 'w'); for your domain website.com having root at /var/www/website/ and if the php file is located at /var/www/website/php/server/file/admin.php or something similar, it will actually create a file at /var/www/website/data.txt
Try giving absolute path or path relative to your domain root to create files like,
$fp = fopen('php/server/file/data.txt', 'w');
Try the find command to see if the file is created anywhere else in the folder directory by using the following in Ubuntu,
find /var/www/website/ -name 'data.txt'
I had this issue, probably can help you solve if you have similar issue.
So, I'm writing a chunked file transfer script that is intended to copy files--small and large--to a remote server. It almost works fantastically (and did with a 26 byte file I tested, haha) but when I start to do larger files, I notice it isn't quite working. For example, I uploaded a 96,489,231 byte file, but the final file was 95,504,152 bytes. I tested it with a 928,670,754 byte file, and the copied file only had 927,902,792 bytes.
Has anyone else ever experienced this? I'm guessing feof() may be doing something wonky, but I have no idea how to replace it, or test that. I commented the code, for your convenience. :)
<?php
// FTP credentials
$server = CENSORED;
$username = CENSORED;
$password = CENSORED;
// Destination file (where the copied file should go)
$destination = "ftp://$username:$password#$server/ftp/final.mp4";
// The file on my server that we're copying (in chunks) to $destination.
$read = 'grr.mp4';
// If the file we're trying to copy exists...
if (file_exists($read))
{
// Set a chunk size
$chunk_size = 4194304;
// For reading through the file we want to copy to the FTP server.
$read_handle = fopen($read, 'rb');
// For appending to the destination file.
$destination_handle = fopen($destination, 'ab');
echo '<span style="font-size:20px;">';
echo 'Uploading.....';
// Loop through $read until we reach the end of the file.
while (!feof($read_handle))
{
// So Rackspace doesn't think nothing's happening.
echo PHP_EOL;
flush();
// Read a chunk of the file we're copying.
$chunk = fread($read_handle, $chunk_size);
// Write the chunk to the destination file.
fwrite($destination_handle, $chunk);
sleep(1);
}
echo 'Done!';
echo '</span>';
}
fclose($read_handle);
fclose($destination_handle);
?>
EDIT
I (may have) confirmed that the script is dying at the end somehow, and not corrupting the files. I created a simple file with each line corresponding to the line number, up to 10000, then ran my script. It stopped at line 6253. However, the script is still returning "Done!" at the end, so I can't imagine it's a timeout issue. Strange!
EDIT 2
I have confirmed that the problem exists somewhere in fwrite(). By echoing $chunk inside the loop, the complete file is returned without fail. However, the written file still does not match.
EDIT 3
It appears to work if I add sleep(1) immediately after the fwrite(). However, that makes the script take a million years to run. Is it possible that PHP's append has some inherent flaw?
EDIT 4
Alright, further isolated the problem to being an FTP problem, somehow. When I run this file copy locally, it works fine. However, when I use the file transfer protocol (line 9) the bytes are missing. This is occurring despite the binary flags the two cases of fopen(). What could possibly be causing this?
EDIT 5
I found a fix. The modified code is above--I'll post an answer on my own as soon as I'm able.
I found a fix, though I'm not sure exactly why it works. Simply sleeping after writing each chunk fixes the problem. I upped the chunk size quite a bit to speed things up. Though this is an arguably bad solution, it should work for my uses. Thanks anyway, guys!
I am running PHP5 on IIS7 on Windows Server 2008 R2. Check out the below code which writes a string received via a POST request parameter into an XML file.
<?php
$temp = "";
if($_SERVER['REQUEST_METHOD']=="POST"){
if($_POST["operation"]=="saveLevels"){
$fileHandle = fopen("c:\\inetpub\\wwwroot\\test\\xml\\levels.xml", 'w');
fwrite($fileHandle, stripslashes($_POST["xmlString"]));
fclose($fileHandle);
$temp = "success";
}elseif($_POST["operation"]=="saveRules"){
$fileHandle = fopen("c:\\inetpub\\wwwroot\\test\\xml\\rules.xml", 'w');
fwrite($fileHandle, stripslashes($_POST["xmlString"]));
fclose($fileHandle);
$temp = "success";
}
}
When I make a POST request to invoke this code, the application pool owning/hosting the site containing php files, stops (due to some fatal errors, as it writes in event viewer) and then IIS keeps responding with HTTP503 after that. Now, I have given proper permissions to IUSR and IISUSRS on that (test/xml) directory. Those two XML files are not already existing, I have also tried the code when an XML file is already present but; it behaved the same way.
What's wrong with that php code? I have tried it on a linux-box and it behaved as expected.
edit: I have tried various different versions of this code and came up with this result: the fopen call when awaken by a POST request, allways returns FALSE or sometimes NULL, and causes the Application Pool of itself to stop. The exact same code, works OK with a GET request, with exact same parameters. So; I dont know what the problem is but; for the time I'm just going to use GET requests for this operation.
Can you var_dump( $fileHandle) for both options, to show us what it has. I notice you're just assuming the file is opened, rather than checking the value (if it's FALSE the fwrite will fail)