我将一个zip文件上传到服务器以进行自动提取。
zip文件的构造如下:
/zip_file.zip/folder1/image1.jpg
/zip_file.zip/folder1/image2.jpg
/zip_file.zip/folder1/image3.jpg
目前我有这个功能来提取所有扩展名为jpg的文件:
$zip = new ZipArchive();
if( $zip->open($file_path) ){
$files = array();
for( $i = 0; $i < $zip->numFiles; $i++){
$entry = $zip->statIndex($i);
// is it an image?
if( $entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'] ) ){
$f_extract = $zip->getNameIndex($i);
$files[] = $f_extract;
}
}
if ($zip->extractTo($dir_name, $files) === TRUE) {
} else {
return FALSE;
}
$zip->close();
}
但是通过使用函数extractTo
,它将作为ff提取到myFolder
:
/myFolder/folder1/image1.jpg
/myFolder/folder1/image2.jpg
/myFolder/folder1/image3.jpg
有没有办法将folder1中的文件解压缩到myFolder的根目录?
理想:
/myFolder/image1.jpg
/myFolder/image2.jpg
/myFolder/image3.jpg
PS:包含冲突文件名我只需要不提取或覆盖文件。
答案 0 :(得分:4)
请改用此小代码段。它删除了每个文件的文件名前面的文件夹结构,以便归档的整个内容基本上被提取到一个文件夹。
<?php
$path = "zip_file.zip";
$zip = new ZipArchive();
if ($zip->open($path) === true) {
for($i = 0; $i < $zip->numFiles; $i++) {
$filename = $zip->getNameIndex($i);
$fileinfo = pathinfo($filename);
copy("zip://".$path."#".$filename, "/myDestFolder/".$fileinfo['basename']);
}
$zip->close();
}
?>
答案 1 :(得分:0)
这里:(我试图管理一切)
$zip = new ZipArchive();
if( $zip->open($file_path) ){
$files = array();
for( $i = 0; $i < $zip->numFiles; $i++){
$entry = $zip->statIndex($i);
// is it an image?
if( $entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'] ) ){
$f_extract = $zip->getNameIndex($i);
$files[] = $f_extract; /* you man want to keep this array (use it to show result or something else) */
if ($zip->extractTo($dir_name, $f_extract) === TRUE) {
$solid_name = basename($f_extract);
if(strpos($f_extract, "/")) // make sure zipped file is in a directory
{
if($dir_name{strlen($dir_name)-1} == "/") $dir_name = substr($dir_name, 0, strlen($dir_name)-1); // to prevent error if $dir_name have slash in end of it
if(!file_exists($dir_name."/".$solid_name)) // you said you don't want to replace existed file
copy($dir_name."/".$f_extract, $dir_name."/".$solid_name); // taking file back to where you need [$dir_name]
unlink($dir_name."/".$f_extract); // [removing old file]
rmdir(str_replace($solid_name, "", $dir_name."/".$f_extract)); // [removing directory of it]
}
} else {
echo("error on export<br />\n");
}
}
}
$zip->close();
}
答案 2 :(得分:0)
您可以使用zip://
语法代替Zip::extractTo
,而不是php manual on extractTo()中所述。
您必须匹配图像文件名,然后将其复制:
if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) {
copy('zip://' . $file_path . '#' . $entry['name'], '/root_dir/' . md5($entry['name']) . '.jpg');
}
以上内容取代了for循环的if语句,使您的extractTo
变得不必要。我使用原始文件名的md5哈希来创建一个唯一的名称。由于哈希冲突很少发生,因此覆盖文件的可能性极小。请注意,这有点重要,相反,您可以str_replace('/.', '', $entry['name'])
创建一个新的唯一文件名。
完整解决方案(代码的修改版本):
<?php
$zip = new ZipArchive();
if ($zip->open($file_path)) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$entry = $zip->statIndex($i);
// is it an image?
if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) {
# use hash (more expensive, but can be useful depending on what you're doing
$new_filename = md5($entry['name']) . '.jpg';
# or str_replace for cheaper, potentially longer name:
# $new_filename = str_replace('/.', '', $entry['name']);
copy('zip://' . $file_path . '#' . $entry['name'], '/myFolder/' . $new_filename);
}
}
$zip->close();
}
?>