创建一个zip文件并下载


Create a zip file and download it

我正试图通过在本地服务器上创建zip文件来下载两个文件。文件是以zip格式下载的,但当我尝试提取它时,它会出现错误:未找到中心目录结尾签名。要么这个文件不是zip文件,或者它构成了多部分归档的一个磁盘。在在后一种情况下,中心目录和zip文件注释将在此存档的最后一个磁盘

我正在使用以下代码:

 <?php
$file_names = array('iMUST Operating Manual V1.3a.pdf','iMUST Product Information Sheet.pdf');
//Archive name
$archive_file_name=$name.'iMUST_Products.zip';
//Download Files path
$file_path=$_SERVER['DOCUMENT_ROOT'].'/Harshal/files/';

zipFilesAndDownload($file_names,$archive_file_name,$file_path);
function zipFilesAndDownload($file_names,$archive_file_name,$file_path)
{
        //echo $file_path;die;
    $zip = new ZipArchive();
    //create the file and throw the error if unsuccessful
    if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
        exit("cannot open <$archive_file_name>'n");
    }
    //add each files of $file_name array to archive
    foreach($file_names as $files)
    {
        $zip->addFile($file_path.$files,$files);
        //echo $file_path.$files,$files."
    }
    $zip->close();
    //then send the headers to force download the zip file
    header("Content-type: application/zip"); 
    header("Content-Disposition: attachment; filename=$archive_file_name"); 
    header("Pragma: no-cache"); 
    header("Expires: 0"); 
    readfile("$archive_file_name");
    exit;
}


?>

我检查了传递到函数中的所有变量的值,它们都很好。所以请看这个。提前谢谢。

添加以字节为单位描述zip文件大小的Content-length标头。

header("Content-type: application/zip"); 
header("Content-Disposition: attachment; filename=$archive_file_name");
header("Content-length: " . filesize($archive_file_name));
header("Pragma: no-cache"); 
header("Expires: 0"); 
readfile("$archive_file_name");

还要确保在<?之前和?>之后绝对没有空白。我在这里看到一个空格:

 <?php
$file_names = array('iMUST Operating Manual V1.3a.pdf','iMUST Product Information Sheet.pdf');
$zip = new ZipArchive;
$tmp_file = 'assets/myzip.zip';
    if ($zip->open($tmp_file,  ZipArchive::CREATE)) {
        $zip->addFile('folder/bootstrap.js', 'bootstrap.js');
        $zip->addFile('folder/bootstrap.min.js', 'bootstrap.min.js');
        $zip->close();
        echo 'Archive created!';
        header('Content-disposition: attachment; filename=files.zip');
        header('Content-type: application/zip');
        readfile($tmp_file);
   } else {
       echo 'Failed!';
   }
// http headers for zip downloads
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename='"".$filename."'"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$filename));
ob_end_flush();
@readfile($filepath.$filename);

我在这里找到了这个解决方案,它对我有效

其中一个错误可能是文件未以"archive"格式读取。检出ZipArchive未打开文件-错误代码:19。在文本编辑器中打开下载的文件,如果在开始时有任何html标记或调试语句,请在读取文件之前清除缓冲区。

ob_clean();
flush();
readfile("$archive_file_name");

我刚刚遇到这个问题。对我来说,问题在于:

readfile("$archive_file_name");

它导致内存不足错误。

Allowed memory size of 134217728 bytes exhausted (tried to allocate 292982784 bytes)

我能够通过用以下内容替换readfile()来纠正这个问题:

    $handle = fopen($zipPath, "rb");
    while (!feof($handle)){
        echo fread($handle, 8192);
    }
    fclose($handle);

不确定这是否是您的相同问题,或者没有看到您的文件只有1.2 MB。也许这会帮助其他有类似问题的人。

我也遇到过同样的问题。在我的案例中,它的来源是我想要在其中创建zip文件的文件夹的权限,这些权限都设置为只读。我把它改成了读写,它起了作用。

如果在运行脚本时没有在本地服务器上创建该文件,则很可能会遇到与我相同的问题。

但下载后我从服务器上得到的文件给出了大小226字节的

这是ZIP标头的大小。显然,下载的ZIP文件中没有数据。那么,您能验证要添加到ZIP文件中的文件是否确实存在(相对于下载PHP脚本的路径)吗?

考虑在addFile上也添加一个检查:

foreach($file_names as $file)
{
    $inputFile = $file_path . $file;
    if (!file_exists($inputFile))
        trigger_error("The input file $inputFile does not exist", E_USER_ERROR);
    if (!is_readable($inputFile))
        trigger_error("The input file $inputFile exists, but has wrong permissions or ownership", E_USER_ERROR);
    if (!$zip->addFile($inputFile, $file))
        trigger_error("Could not add $inputFile to ZIP file", E_USER_ERROR);
}

观察到的行为与阻止文件添加到ZIP文件的一些问题(路径错误、权限问题等)一致。在接收到"空"ZIP文件时,客户端会发出一个错误,指出缺少ZIP中心目录(实际错误是没有目录,也没有文件)。

确保$archive_file_name内的路径正确且确实存在。在代码中,您通过放置未声明的前缀变量$name来更新$archive_file_name变量。

$archive_file_name = $name.'iMUST_Products.zip';

如果路径不正确且找不到,则创建的压缩文件无处可去,两个文件也无处存储。要存储的文件的路径也应该存在。

假设您只想自定义要下载的压缩文件夹的名称,这就是为什么有一个$name变量来防止冗余文件名的原因。但是您必须考虑运行脚本的URI。

例如,您正在使用URI路由,并在https://sample.co/file-management/download-zipped-111.使用当前脚本,压缩后的文件夹将存储在file-management文件夹中。如果它不存在,你将主要遇到你现在正在经历的错误。

解决方案是明确声明压缩文件将存储的文件夹的路径。

例如,您希望将压缩后的文件存储在Harshal/files/zipped/中。通过在files文件夹中创建名为zipped的文件夹来确保此文件夹存在,并且您有权对此文件夹进行写入。

$file_names = array('iMUST Operating Manual V1.3a.pdf', 'iMUST Product Information Sheet.pdf');
// $name should be declared before this line
$archive_file_name = $name.'iMUST_Products.zip';
//Download Files path
$file_path = $_SERVER['DOCUMENT_ROOT'].'/Harshal/files/';
zipFilesAndDownload($file_names, $archive_file_name, $file_path);
function zipFilesAndDownload($file_names, $archive_file_name, $file_path)
{
    $zip = new ZipArchive();
    // WE REUSED THE $file_path VARIABLE HERE THEN ADDED zipped FOLDER
    if ($zip->open($file_path.'zipped/'.$archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
        exit('cannot open <'.$archive_file_name.'>');
    }
    //add each files of $file_name array to archive
    foreach($file_names as $files)
    {
        $zip->addFile($file_path.$files, $files);
    }
    $zip->close();
    //then send the headers to force download the zip file
    header("Content-type: application/zip"); 
    header("Content-Disposition: attachment; filename=$archive_file_name"); 
    header('Content-length: '.filesize($file_path.'zipped/'.$archive_file_name));
    header("Pragma: no-cache"); 
    header("Expires: 0"); 
    readfile("$archive_file_name");
    exit;
}

人们可能会建议——";为什么不直接将$archive_file_name变量的完整路径?

$archive_file_name = $file_path.'zipped/'.$name.'iMUST_Products.zip';

如果我们将其直接放在$archive_file_name变量中,那么将要下载的文件很可能命名为/var/www/Harshal/files/zipped/xxx-iMUST_Products.zip