在PHP中压缩文件夹的内容 [英] Zipping the contents of a folders in PHP
问题描述
在将此信息标记为重复之前,请注意,我已经在SO上搜索答案,而且我发现到目前为止(下面列出)并不是我一直在寻找的。
<这些只是我看过的一些。
我的问题是:我不能使用addFromString,我有使用addFile,这是任务的要求。 >
我已经尝试了几种方法,这里是我当前的迭代:
public function getZippedFiles($ path)
{
$ real_path = WEBROOT_PATH。$ path;
$ files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($ real_path),RecursiveIteratorIterator :: LEAVES_ONLY);
//#创建一个临时文件&打开它
$ tmp_file = tempnam($ real_path,'');
$ zip_file = preg_replace('\.tmp $','.zip',$ tmp_file);
$ zip = new ZipArchive();
$ zip-> open($ zip_file,ZipArchive :: CREATE);
foreach($ files as $ name => $ file)
{
error_log(print_r($ name,true));
error_log(print_r($ file,true));
if(($ file ==。)||($ file ==..))
{
continue;
}
$ file_path = $ file-> getRealPath();
$ zip-> addFile($ file_path);
}
$ zip-> close();
}
当我尝试打开生成的文件时,打开文件夹压缩(压缩)文件夹''无效。
我已经成功地使用addFromString完成任务,如下:
$ file_path = WEBROOT_PATH。$ path;
$ files = array();
if(is_dir($ file_path)== true)
{
if($ handle = opendir($ file_path))
{
while(($ file = readdir($ handle))!== false)
{
if(is_dir($ file_path。$ file)== false)
{
$ files [] = $ file_path 。\\。$ file;
}
}
//#create new zip opbject
$ zip = new ZipArchive();
//#创建一个临时文件&打开它
$ tmp_file = tempnam($ file_path,'');
$ zip_file = preg_replace('\.tmp $','.zip',$ tmp_file);
$ zip-> open($ zip_file,ZipArchive :: CREATE);
//#循环遍历每个文件
foreach($ files as $ file){
//#下载文件
$ download_file = file_get_contents $ file);
//#将其添加到zip
$ zip-> addFromString(basename($ file),$ download_file);
}
//#close zip
$ zip-> close();
}
}
}
直接从一些示例代码我看到的地方。如果任何人都能指出我的方向,我会非常感谢!
*****更新*****
我添加了一个if这样的结果如下:
if(!$ zip-> close()){
echofailed写邮政归档;
}
消息被回传,所以很明显问题出在那里。我还检查以确保 $ zip-> open()
工作,我已经确认它是打开它没有问题。
最后设法使用 addFile
工作。
我创建了一个包含3个函数的帮助类:一个列出目录中的所有文件,1个压缩所有这些文件,1个下载压缩文件:
<?php
require_once($ _ SERVER [DOCUMENT_ROOT]。/ config.php);
class FileHelper extends ZipArchive
{
/ **
*列出dir中的文件
*
*此函数需要一个绝对路径作为目标的文件夹。
*该函数将尝试创建一个数组,其中包含目标目录中所有文件(
*除外)的完整路径。和$ ..
*
* @param dir [string]:目标目录的绝对路径
*
* @return result [array]:指向文件的绝对路径数组在目标目录
* /
public static function listDirectory($ dir)
{
$ result = array();
$ root = scandir($ dir);
foreach($ root as $ value){
if($ value ==='。'|| $ value ==='..'){
continue;
}
if(is_file($ dir $ value)){
$ result [] =$ dir $ value;
continue;
}
if(is_dir($ dir $ value)){
$ result [] =$ dir $ value /;
}
foreach(self :: listDirectory($ dir $ value /)as $ value)
{
$ result [] = $ value;
}
}
return $ result;
}
/ **
*压缩和下载文件
*
*此函数需要目录位置作为临时文件的目标, list(array)
*将被压缩并添加到zip文件的绝对文件名。压缩后,
*临时压缩文件将被下载和删除。
*
* @param location [string]:将包含temp文件的目录的绝对路径
* @param file_list [array]:指向需要的文件的绝对路径数组被压缩
*
* @return void
* /
public function downloadZip($ file)
{
$ modules = apache_get_modules
if(in_array('mod_xsendfile',$ modules))//注意,不可能检测到X-SendFile是否打开,我们只能检查模块是否安装。如果X-SendFile安装但关闭,文件下载将不起作用
{
header(Content-Type:application / octet-stream);
header('Content-Disposition:attachment; filename ='。basename($ file)。'');
header(X-Sendfile:.realpath(dirname(__ FILE __))。$ file);
// Apache将处理剩下的事情,因此终止脚本
exit;
}
header(Content-Type:application / octet-stream);
header(Content-Length:。(string)(filesize($ file)));
header('Content-Disposition:attachment; filename ='。basename($ file)。'');
header(Content-Transfer-Encoding:binary);
header(Expires:0);
header(Cache-Control:no-cache,must-revalidate);
header(Cache-Control:private);
header(Pragma:public);
ob_end_clean(); //没有这个,文件将被读入输出缓冲区,破坏大文件上的内存
readfile($ file);
}
/ **
* Zips文件
*
*此函数需要一个目录位置作为临时文件的目标, array)
*绝对文件名,它们将被压缩并添加到一个zip文件中。
*
* @param location [string]:将包含temp文件的目录的绝对路径
* @param file_list [array]:指向需要的文件的绝对路径数组被压缩
*
* @return zip_file [string]:新压缩文件的绝对文件路径
* /
public function zipFile($ location,$ file_list)
{
$ tmp_file = tempnam($ location,'');
$ zip_file = preg_replace('\.tmp $','.zip',$ tmp_file);
$ zip = new ZipArchive();
if($ zip-> open($ zip_file,ZIPARCHIVE :: CREATE)=== true)
{
foreach($ file_list as $ file)
{
if($ file!== $ zip_file)
{
$ zip-> addFile($ file,substr($ file,strlen($ location)));
}
}
$ zip-> close();
}
//删除临时文件
unlink($ tmp_file);
return $ zip_file;
}
}
?>
以下是我调用此类的函数的方法:
$ location =d:/ some / path / to / file /;
$ file_list = $ file_helper :: listDirectory($ location);
$ zip_file = $ file_helper-> zipFile($ location,$ file_list);
$ file_helper-> downloadZip($ zip_file);
Before marking this post as a duplicate, please note that I have already searched for answer on SO and the once I've found so far (listed below) haven't been exactly what I've been looking for.
- How to [recursively] Zip a directory in PHP?
- using zipArchive addFile() will not add image to zip
- ZipArchive - addFile won't work
Those are just some of the ones I've looked at.
My problem is this: I can't use addFromString, I have to use addFile, it's a requirement of the task.
I've already tried a couple of ways, here's my current iteration:
public function getZippedFiles($path)
{
$real_path = WEBROOT_PATH.$path;
$files = new RecursiveIteratorIterator (new RecursiveDirectoryIterator($real_path), RecursiveIteratorIterator::LEAVES_ONLY);
//# create a temp file & open it
$tmp_file = tempnam($real_path,'');
$zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);
$zip = new ZipArchive();
$zip->open($zip_file, ZipArchive::CREATE);
foreach ($files as $name=>$file)
{
error_log(print_r($name, true));
error_log(print_r($file, true));
if ( ($file == ".") || ($file == "..") )
{
continue;
}
$file_path = $file->getRealPath();
$zip->addFile($file_path);
}
$zip->close();
}
When I try to open the resulting file, I get told that "Windows cannot open the folder. The Compressed(zipped) Folder '' is invalid."
I've managed to succesfully complete the task using addFromString, like so:
$file_path = WEBROOT_PATH.$path;
$files = array();
if (is_dir($file_path) == true)
{
if ($handle = opendir($file_path))
{
while (($file = readdir($handle)) !== false)
{
if (is_dir($file_path.$file) == false)
{
$files[] = $file_path."\\".$file;
}
}
//# create new zip opbject
$zip = new ZipArchive();
//# create a temp file & open it
$tmp_file = tempnam($file_path,'');
$zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);
$zip->open($zip_file, ZipArchive::CREATE);
//# loop through each file
foreach($files as $file){
//# download file
$download_file = file_get_contents($file);
//#add it to the zip
$zip->addFromString(basename($file),$download_file);
}
//# close zip
$zip->close();
}
}
}
The above is mostly just copied straight from some example code I saw somewhere. If anyone can point me in a good direction I'd be very grateful!
***** UPDATE ***** I added an if around the close like this:
if (!$zip->close()) {
echo "failed writing zip to archive";
}
The message gets echoed out, so obviously the problem is there. I've also checked to make sure the $zip->open()
works, and I've confirmed that it is opening it without a problem.
Finally managed to get something working using addFile
.
I created a helper class that contains 3 functions: one to list all the files in a directory, 1 to zip all those files, and 1 to download the zipped files:
<?php
require_once($_SERVER["DOCUMENT_ROOT"]."/config.php");
class FileHelper extends ZipArchive
{
/**
* Lists files in dir
*
* This function expects an absolute path to a folder intended as the target.
* The function will attempt to create an array containing the full paths to
* all files in the target directory, except for . and ..
*
* @param dir [string] : absolute path to the target directory
*
* @return result [array] : array of absolute paths pointing to files in the target directory
*/
public static function listDirectory($dir)
{
$result = array();
$root = scandir($dir);
foreach($root as $value) {
if($value === '.' || $value === '..') {
continue;
}
if(is_file("$dir$value")) {
$result[] = "$dir$value";
continue;
}
if(is_dir("$dir$value")) {
$result[] = "$dir$value/";
}
foreach(self::listDirectory("$dir$value/") as $value)
{
$result[] = $value;
}
}
return $result;
}
/**
* Zips and downloads files
*
* This function expects a directory location as target for a temp file, and a list(array)
* of absolute file names that will be compressed and added to a zip file. After compression,
* the temporary zipped file will be downloaded and deleted.
*
* @param location [string] : absolute path to the directory that will contain the temp file
* @param file_list [array] : array of absolute paths pointing to files that need to be compressed
*
* @return void
*/
public function downloadZip($file)
{
$modules = apache_get_modules();
if (in_array('mod_xsendfile', $modules)) // Note, it is not possible to detect if X-SendFile is turned on or not, we can only check if the module is installed. If X-SendFile is installed but turned off, file downloads will not work
{
header("Content-Type: application/octet-stream");
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header("X-Sendfile: ".realpath(dirname(__FILE__)).$file);
// Apache will take care of the rest, so terminate the script
exit;
}
header("Content-Type: application/octet-stream");
header("Content-Length: " .(string)(filesize($file)) );
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header("Content-Transfer-Encoding: binary");
header("Expires: 0");
header("Cache-Control: no-cache, must-revalidate");
header("Cache-Control: private");
header("Pragma: public");
ob_end_clean(); // Without this, the file will be read into the output buffer which destroys memory on large files
readfile($file);
}
/**
* Zips files
*
* This function expects a directory location as target for a temp file, and a list(array)
* of absolute file names that will be compressed and added to a zip file.
*
* @param location [string] : absolute path to the directory that will contain the temp file
* @param file_list [array] : array of absolute paths pointing to files that need to be compressed
*
* @return zip_file [string] : absolute file path of the freshly zipped file
*/
public function zipFile($location, $file_list)
{
$tmp_file = tempnam($location,'');
$zip_file = preg_replace('"\.tmp$"', '.zip', $tmp_file);
$zip = new ZipArchive();
if ($zip->open($zip_file, ZIPARCHIVE::CREATE) === true)
{
foreach ($file_list as $file)
{
if ($file !== $zip_file)
{
$zip->addFile($file, substr($file, strlen($location)));
}
}
$zip->close();
}
// delete the temporary files
unlink($tmp_file);
return $zip_file;
}
}
?>
Here's how I called this class's functions:
$location = "d:/some/path/to/file/";
$file_list = $file_helper::listDirectory($location);
$zip_file = $file_helper->zipFile($location, $file_list);
$file_helper->downloadZip($zip_file);
这篇关于在PHP中压缩文件夹的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!