I have the following code that downloads a zip file from an external source and then extracts it:
file_put_contents("my-zip.zip", fopen("http://www.externalsite.com/zipfile.zip", 'r'));
$zip = new ZipArchive;
$res = $zip->open('my-zip.zip');
if ($res === TRUE) {
$zip->extractTo('/extract-here');
$zip->close();
//
} else {
//
}
This works fine, however my question is, does the unzipping procedure wait until the file_put_contents function is complete? Or will it try and run half way through?
It seems to work fine right now but I'm thinking that if the zip file download is delayed or slow for whatever reason that it may crash why trying to unzip a file that doesn't exist.
If that makes sense.
file_put_contents can work differently depending on the host machine, but as far as I can tell its format doesn't lock concurrent threads as one should expect (unless strictly specified). Also good to remember PHP behaves differently on windows than it does in linux (and many people, not telling you do, develop in windows to then deploy on a linux server)
You can try something like this to guarantee that the file was successfully downloaded. (And that no concurrent thread same time);
$file = fopen("my-zip.zip", "w+");
if (flock($file, LOCK_EX)) {
fwrite($file, fopen("http://www.externalsite.com/zipfile.zip", 'r'));
$zip = new ZipArchive;
$res = $zip->open('my-zip.zip');
if ($res === TRUE) {
$zip->extractTo('/extract-here');
$zip->close();
//
} else {
//
}
flock($file, LOCK_UN);
} else {
// die("Couldn't download the zip file.");
}
fclose($file);
This might also work.
$f = file_put_contents("my-zip.zip", fopen("http://www.externalsite.com/zipfile.zip", 'r'), LOCK_EX);
if(FALSE === $f)
die("Couldn't write to file.");
$zip = new ZipArchive;
$res = $zip->open('my-zip.zip');
if ($res === TRUE) {
$zip->extractTo('/extract-here');
$zip->close();
//
} else {
//
}
This will prevent in case you call this page twice and both pages try to access the same file. This is what could happen: Page 1 downloads zip. Page 1 starts extracting zip. Page 2 downloads zip replacing the old one Page 1 will be like: What happened to my zip? O.O
Try something like this
function downloadUnzipGetContents($url) {
$data = file_get_contents($url);
$path = tempnam(sys_get_temp_dir(), 'prefix');
$temp = fopen($path, 'w');
fwrite($temp, $data);
fseek($temp, 0);
fclose($temp);
$pathExtracted = tempnam(sys_get_temp_dir(), 'prefix');
$filenameInsideZip = 'test.csv';
copy("zip://".$path."#".$filenameInsideZip, $pathExtracted);
$data = file_get_contents($pathExtracted);
unlink($path);
unlink($pathExtracted);
return $data;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With