У меня есть папка с именем «data». В этой папке «data» содержится файл «filecontent.txt» и другая папка с именем «Файлы». Папка «Файлы» содержит файл «info.txt». Таким образом, это папка внутри структуры папок.
Я должен застегнуть эту папку «данные» (используя php) вместе с файлом и папкой внутри нее и загрузить заархивированный файл.
Я попробовал примеры, доступные на http://www.php.net/manual/en/zip.examples.php. Эти примеры не сработали. Моя версия PHP – 5.2.10
Пожалуйста помоги.
Я написал этот код.
<?php $zip = new ZipArchive; if ($zip->open('check/test2.zip',ZIPARCHIVE::CREATE) === TRUE) { if($zip->addEmptyDir('newDirectory')) { echo 'Created a new directory'; } else { echo 'Could not create directory'; } $zipfilename="test2.zip"; $zipname="check/test2.zip"; header('Content-Type: application/zip'); header('Content-disposition: attachment; filename=check/test1.zip'); //header('Content-Length: ' . filesize( $zipfilename)); readfile($zipname); //$zip->close(); } else { echo failed'; } ?>
файл загружен, но не может распаковать
Вам нужно рекурсивно добавлять файлы в каталог. Что-то вроде этого (непроверено):
function createZipFromDir($dir, $zip_file) { $zip = new ZipArchive; if (true !== $zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) { return false; } zipDir($dir, $zip); return $zip; } function zipDir($dir, $zip, $relative_path = DIRECTORY_SEPARATOR) { $dir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; if ($handle = opendir($dir)) { while (false !== ($file = readdir($handle))) { if (file === '.' || $file === '..') { continue; } if (is_file($dir . $file)) { $zip->addFile($dir . $file, $file); } elseif (is_dir($dir . $file)) { zipDir($dir . $file, $zip, $relative_path . $file); } } } closedir($handle); }
Затем вызовите $zip = createZipFromDir('/tmp/dir', 'files.zip');
Для еще большего выигрыша я бы рекомендовал прочитать здесь SPL DirectoryIterator
Помещает все подпапки и подфайлы со своей структурой:
<?php $the_folder = 'path/foldername'; $zip_file_name = 'archived_name.zip'; $download_file= true; //$delete_file_after_download= true; doesnt work!! class FlxZipArchive extends ZipArchive { /** Add a Dir with Files and Subdirs to the archive;;;;; @param string $location Real Location;;;; @param string $name Name in Archive;;; @author Nicolas Heimann;;;; @access private **/ public function addDir($location, $name) { $this->addEmptyDir($name); $this->addDirDo($location, $name); } // EO addDir; /** Add Files & Dirs to archive;;;; @param string $location Real Location; @param string $name Name in Archive;;;;;; @author Nicolas Heimann * @access private **/ private function addDirDo($location, $name) { $name .= '/'; $location .= '/'; // Read all Files in Dir $dir = opendir ($location); while ($file = readdir($dir)) { if ($file == '.' || $file == '..') continue; // Rekursiv, If dir: FlxZipArchive::addDir(), else ::File(); $do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile'; $this->$do($location . $file, $name . $file); } } // EO addDirDo(); } $za = new FlxZipArchive; $res = $za->open($zip_file_name, ZipArchive::CREATE); if($res === TRUE) { $za->addDir($the_folder, basename($the_folder)); $za->close(); } else { echo 'Could not create a zip archive';} if ($download_file) { ob_get_clean(); header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=" . basename($zip_file_name) . ";" ); header("Content-Transfer-Encoding: binary"); header("Content-Length: " . filesize($zip_file_name)); readfile($zip_file_name); //deletes file when its done... //if ($delete_file_after_download) //{ unlink($zip_file_name); } } ?>
Я должен был сделать то же самое несколько дней назад, и вот что я сделал.
1) Получить структуру файлов / папок и заполнить массив элементов. Каждый элемент является либо файлом, либо папкой, если это папка, так же, как и содержимое, возвращает содержимое.
2) Разберите этот массив и создайте zip-файл.
Поместите мой код ниже, вам, конечно, придется адаптировать его в зависимости от того, как было создано ваше приложение.
// Get files $items['items'] = $this->getFilesStructureinFolder($folderId); $archiveName = $baseDir . 'temp_' . time(). '.zip'; if (!extension_loaded('zip')) { dl('zip.so'); } //all files added now $zip = new ZipArchive(); $zip->open($archiveName, ZipArchive::OVERWRITE); $this->fillZipRecursive($zip, $items); $zip->close(); //outputs file if (!file_exists($archiveName)) { error_log('File doesn\'t exist.'); echo 'Folder is empty'; return; } header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=" . basename($archiveName) . ";" ); header("Content-Transfer-Encoding: binary"); header("Content-Length: " . filesize($archiveName)); readfile($archiveName); //deletes file when its done... unlink($archiveName);
Методы, используемые для заполнения и анализа:
/** * * Gets all the files recursively within a folder and keeps the structure. * * @param int $folderId The id of the folder from which we start the search * @return array $tree The data files/folders data structure within the given folder id */ public function getFilesStructureinFolder($folderId) { $result = array(); $query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND status = 1 AND parent_folder_id = ? ORDER BY name ASC', $folderId); $folders = $query->result(); foreach($folders as $folder) { $folderItem = array(); $folderItem['type'] = 'folder'; $folderItem['obj'] = $folder; $folderItem['items'] = $this->getFilesStructureinFolder($folder->id); $result[] = $folderItem; } $query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND xx = ? AND status = 1 ORDER BY name ASC', $folderId); $files = $query->result(); foreach ($files as $file) { $fileItem = array(); $fileItem['type'] = 'file'; $fileItem['obj'] = $file; $result[] = $fileItem; } return $result; } /** * Fills zip file recursively * * @param ZipArchive $zip The zip archive we are filling * @param Array $items The array representing the file/folder structure * @param String $zipPath Local path within the zip * */ public function fillZipRecursive($zip, $items, $zipPath = '') { $baseDir = $this->CI->config->item('xxx'); foreach ($items['items'] as $item) { //Item is a file if ($item['type'] == 'file') { $file = $item['obj']; $fileName = $baseDir . '/' . $file->fs_folder_id . '/' . $file->file_name; if (trim($file->file_name) == '' || !file_exists($fileName)) continue; $zip->addFile($fileName, $zipPath.''.$file->file_name); } //Item is a folder else if ($item['type'] == 'folder') { $folder = $item['obj']; $zip->addEmptyDir($zipPath.''.$folder->name); //Folder probably has items in it! if (!empty($item['items'])) $this->fillZipRecursive($zip, $item, $zipPath.'/'.$folder->name.'/'); } } }
См. Связанные дубликаты. Другой часто упущенный и конкретный ленивый вариант:
exec("zip -r data.zip data/"); header("Content-Type: application/zip"); readfile("data.zip"); // must be a writeable location though
Используйте класс TbsZip для создания нового архива ZIP. TbsZip прост, он не использует временные файлы, не ZIP-EXE, он не имеет зависимости и имеет функцию загрузки, которая сбрасывает архив в качестве файла загрузки.
Вам просто нужно зациклиться под деревом папок и добавить все файлы в архив, а затем очистить его.
Пример кода:
$zip = new clsTbsZip(); // instantiate the class $zip->CreateNew(); // create a virtual new zip archive foreach (...) { // your loop to scann the folder tree ... // add the file in the archive $zip->FileAdd($FileInnerName, $LocalFilePath, TBSZIP_FILE); } // flush the result as an HTTP download $zip->Flush(TBSZIP_DOWNLOAD, 'my_archive.zip');
Файлы, добавленные в архив, будут последовательно сжаты во время метода Flush (). Таким образом, ваш архив может содержать множество подфайлов, это не увеличит память PHP.