I need to duplicate (not move) a 28Mb file copying it from one directory to another on the same server. I have created a PHP (Version 5.3.28) script to do this but, once the copy() function is called, the output of the script is stopped.
I did a search here before posting - no similar topics found.
It’s not a PHP timeout as the copy function proceeds until the full file has been copied. I’ve extended (and reduced) the timeout with no visible impact.
The output is not buffered, it simply stops after the call to the copy() function. flush() does not correct the problem.
There are no errors reported and the script validates correctly.
I am not changing the file name and I am providing the full path (same result as relative path).
It is not a file permission problem, either, as the file copies to completion (file size confirmed via FTP).
// DOCUMENT_ROOT is set by a prior define() statement
// $dir and $file are previously assigned
if(!copy(DOCUMENT_ROOT."$dir/$file", DOCUMENT_ROOT."$file"))
{
echo "$file copy failed.</p>";
} else {
echo "$dir/$file successfully copied to parent directory.</p>";
}
I had had it working through to the bottom of the page but can’t use my “Way Back Machine” to recreate my original script (which may not have checked the boolean response from the copy() function).
Make it as verbose as possible (INFO, WARNINGS, etc). I think you are at the point where you can really use as much info as you can get that PHP will throw out to you.
I’ve been trying to search on this topic and, man is that a challenge! copy is used for a variety of things so its hard to narrow the search terms and still be on topic.
From a quick glance, I don’t see anything wrong. All I can think of is that the copy is exceeding the buffer output and clearing it out. But that is all theoretical at this point.
… with NO effect, i.e., the script ran displaying all input up to the copy() function then continued without any output until the copy was finished (from the twirling image on the tab and “transferring data” in the status area of FF). Nothing was added to the original output (no errors, warnings, notices, yadda yadda).
At least with the input so far, I’m apparently not crazy after all! Okay, that may be debatable so my comment is limited to this copy() function problem. Thanks!
Out of curiosity are you willing to forgo the built in copy method and use exec or shell_exec to run “cp file1 file2 >2&1”? And if so, does it work better?
I created a tiny text file in the subdirectory and it copied immediately with the script running to the end of the file. Apparently, the size of the copy() file is relevant. I’d hate to have to test all the way up to 29Mb to find the break point but …
Moreover, I’d hate to have to figure out a workaround for the larger file (other than to abandon the script - allow a link out - after starting the copy() function allowing it to complete the copy() without a success/fail notice).
This is a part of a “Website Manager” for a client so, no, that’s not an option (although it should work fine, too).
The problem with my copy script is ONLY that its output to the browser ceases upon executing copy() on a large file. The file DOES copy perfectly (whether I’ve linked away during the copy() or not); it simply discontinues the output to the webpage so a success/fail message and reserving the “link out” until completion is not possible. Simply holding all output in a buffer would have my client sitting for ~30 sec. waiting for the script to report anything isn’t acceptable, either (I believe ALL clients are members of the “Short Attention Span Theater” club - they want to be entertained while the script is working!).
Side note: Earlier you made it sound that placing the copy() in the “if” statement may have caused it to break the output. If you take it back out of the if statement and use file_exists($dest) does that work?
Oh, lastly, and this is a last ditch effort because it requires altering your entire process. Use Ajax for the copy process. You can kick it off on an ajax request, then use setInterval to run a file_exists($dest) and check its size to verify it is completed.
I started with a copy() result being assigned to a value ($okay) then using an if … then … else structure for my success/fail reporting. That didn’t work so I moved to the embedded if(!copy()) structure. I’m fully aware that there’s more than one way to skin a cat and I believe I’ve tried all (EXCEPT abandoning copy() and using a read/write function pair which is just too ugly to contemplate).
Hmmm, that requires removing my PHP cap and actually thinking about using JavaScript on what should be a simple thing for PHP to accomplish. As you say, though, last ditch may require something like this. Since I’m too tired to think (JS) at the moment, I’ll have to give it a try after I’ve rested and refreshed.
THANKS for the suggestion, though. 'Love the thinking out of the box!
I have resolved this by modifying a contributed function found on php.net (courtesy of felix dot nensa at gmail dot com) which allows me to embed “eye candy” for my client AND completes the script:
function pipe_streams($in, $out)
{
$size = 0;
while (!feof($in)) $size += fwrite($out,fread($in,8192));
return $size;
}
Utilizing this function, the file is copied AND the script completes allowing a success/fail message AND withholding a link off the page until the code is complete. Note: I added “eye candy” for my client which provided immediate feedback on every 8k chunk of the 28.8Mb file, something I could not do with the copy() function.
It is apparent that there is a buffer limit on the copy() function (it didn’t work with an 8,290,348 byte file either) so I had to abandon the obvious copy() function in favor of reading/writing 8k chunks at a time. Yes, the very same “read/write function pair which is just too ugly to contemplate.”
cprado was on this track, too, but suggested using AJAX to perform the copy function “offline” and providing the feedback to the original script. :tup:
Sweet! Glad that did the trick without having to result into an Ajax last ditch effort! Thanks for reporting it back, this is one I’ll definitely keep in mind should I ever need it.
That still leaves me wondering WHY copy() is not as useful as it should be. Okay, it did succeed in copying the 28.8Mb file (even when I left the page before completion) but stopping the script output is a terrible thing for it to do. I’d love to hear from the PHP team as to why that occurs.
No worries about the feedback. I’ve been in your TL shoes and know the value of good feedback on problematic threads.
Again, thanks for the push in the right direction.