如果您的服务器允许从 PHP 执行 shell 命令,并且安装了 zip,您可以使用 passthru( "zip - directory" ) 即时生成 zip。 - 表示要写入 stdout,这样您就不必处理临时文件清理。
下面是这样一个脚本的概要:
<?php
if ( ! $dir = get_my_directory() )
die("Illegal call.");
header( 'Content-Type: application/zip' );
header( 'Content-Disposition: attachment; filename=\"your.zip\"' );
passthru( 'zip -r - ' . escapeshellarg( $dir ) );
/**
* @return false/null or the directory to zip.
*/
function get_my_directory() {
....
return ....;
}
无论您如何实现get_my_directory(),请确保任何人都无法在您的服务器上指定任何路径!
另外,不要生成任何输出(没有 echo/print 或警告),因为这样要么不会设置标头,要么会损坏 zip 二进制数据。
除此之外,PHP 的ZipArchive 页面上还有代码示例和文档。
更新
(@ OP:如果你不懂 PHP,我不太确定你在做什么来实现 PHP 解决方案。但是,假设你想学习。)
假设您有 3 个公共目录可供下载,并且任何人都可以下载它们。您将实现如下:
function get_my_directory() {
// list of the directories you want anyone to be able to download.
// These are key-value pairs, so we can use the key in our URLs
// without revealing the real directories.
$my_directories = array(
'dir1' => 'path/to/dir1/',
'dir2' => 'path/to/dir2/',
'dir3' => 'path/to/dir3/'
);
// check if the 'directory' HTTP GET parameter is given:
if ( ! isset( $_GET['directory'] ) )
return null; // it's not set: return nothing
else
$dir = $_GET['directory']; // it's set: save it so we don't have
// to type $_GET['directory'] all the time.
// validate the directory: only pre-approved directories can be downloaded
if ( ! in_array( $dir, array_keys( $my_directories ) ) )
return null; // we don't know about this directory
else
return $my_directories[ $dir ]; // the directory: is 'safe'.
}
是的,您将第一个和第二个代码示例粘贴到一个 .php 文件中(确保将第一个 get_my_directory 函数替换为第二个),位于服务器上可访问的某个位置。
如果您调用文件“download-archive.php”,并将其放在 DocumentRoot 中,
您可以以http://your-site/download-archive.php?directory=dir1 等身份访问它。
以下是一些参考资料:
更新 2
这是使用 ZipArchive 的完整脚本。它只在目录中添加文件;没有子目录。
<?php
if ( ! $dir = get_my_directory() )
die("Illegal call.");
$zipfile = make_zip( $dir );
register_shutdown_function( function() use ($zipfile) {
unlink( $zipfile ); // delete the temporary zip file
} );
header( "Content-Type: application/zip" );
header( "Content-Disposition: attachment; filename=\"$zipfile\"" );
readfile( $zipfile );
function make_zip( $dir )
{
$zip = new ZipArchive();
$zipname = 'tmp_'.basename( $dir ).'.zip'; // construct filename
if ($zip->open($zipname, ZIPARCHIVE::CREATE) !== true)
die("Could not create archive");
// open directory and add files in the directory
if ( !( $handle = opendir( $dir ) ) )
die("Could not open directory");
$dir = rtrim( $dir, '/' ); // strip trailing /
while ($filename = readdir($handle))
if ( is_file( $f = "$dir/$filename" ) )
if ( ! $zip->addFile( $f, $filename ) )
die("Error adding file $f to zip as $filename");
closedir($handle);
$zip->close();
return $zipname;
}
/**
* @return false/null or the directory to zip.
*/
function get_my_directory() {
// list of the directories you want anyone to be able to download.
// These are key-value pairs, so we can use the key in our URLs
// without revealing the real directories.
$my_directories = array(
'dir1' => 'path/to/dir1/',
'dir2' => 'path/to/dir2/',
'dir3' => 'path/to/dir3/'
);
// check if the 'directory' HTTP GET parameter is given:
if ( ! isset( $_GET['directory'] ) )
return null; // it's not set: return nothing
else
$dir = $_GET['directory']; // it's set: save it so we don't have
// to type $_GET['directory'] all the time.
// validate the directory: only pre-approved directories can be downloaded
if ( ! in_array( $dir, array_keys( $my_directories ) ) )
return null; // we don't know about this directory
else
return $my_directories[ $dir ]; // the directory: is 'safe'.
}