简体   繁体   English

使用 php 压缩和下载文件

[英]zip and download files using php

I am trying to zip and download files from a folder named "upload".我正在尝试从名为“上传”的文件夹中压缩和下载文件。 Zip file is downloading but I couldn't open (extract) it.正在下载 Zip 文件,但我无法打开(提取)它。 I am getting an error like "The archive is either in unknown format or damaged".我收到类似“存档格式未知或已损坏”的错误消息。

I have found the following code to zip the folder.我找到了以下代码来压缩文件夹。

<?php
    $files = "upload/".array('Dear GP.docx','ecommerce.doc');
    $zipname = 'filename.zip';
    $zip = new ZipArchive;
    $zip->open($zipname, ZipArchive::CREATE);
    foreach ($files as $file) {
      $zip->addFile($file);
    }
    $zip->close();
    header('Content-Type: application/zip');
    header('Content-disposition: attachment; filename=filename.zip');
    header('Content-Length: ' . filesize($zipfilename));
    readfile($zipname);
?>

Thanks for your answers.感谢您的回答。

<?php
    $files = array('Dear GP.docx','ecommerce.doc');

    # create new zip opbject
    $zip = new ZipArchive();

    # create a temp file & open it
    $tmp_file = tempnam('.','');
    $zip->open($tmp_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();

    # send the file to the browser as a download
    header('Content-disposition: attachment; filename=Resumes.zip');
    header('Content-type: application/zip');
    readfile($tmp_file);
 ?>

I had spent more than 6 hours on this downloading zip files on my mac (localhost) - Though the file was getting downloaded, I could not unzip them (getting cpgz files).我在我的 mac(本地主机)上花了 6 个多小时来下载这个 zip 文件 - 尽管文件正在下载,但我无法解压缩它们(获取 cpgz 文件)。 Apparently, none of the solutions mentioned in stack overflow (around a variety of questions on zip file download) worked.显然,堆栈溢出中提到的所有解决方案(围绕 zip 文件下载的各种问题)都没有奏效。 Finally, after trial and error, I found that the following code works:最后,经过反复试验,我发现以下代码有效:

None of the people answered earlier talked about the ob_start() and where exactly you should put it.之前回答的人都没有谈到 ob_start() 以及您应该把它放在哪里。 Anyway, that alone was not the answer - you need to use those three lines above ob_start() too.无论如何,仅此而已不是答案-您也需要使用 ob_start() 上方的那三行。

$file=$zippath.$filename;
if (headers_sent()) {
    echo 'HTTP header already sent';
} else {
    if (!is_file($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
        echo 'File not found';
    } else if (!is_readable($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
        echo 'File not readable';
    } else {
        while (ob_get_level()) {
            ob_end_clean();
        }
       ob_start();
       header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
       header("Content-Type: application/zip");
       header("Content-Transfer-Encoding: Binary");
       header("Content-Length: ".filesize($file));
       header('Pragma: no-cache');
       header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
       ob_flush();
       ob_clean();
       readfile($file);
       exit;
   }
}

Please use below code instead of $zip->addFile($file);请使用下面的代码而不是$zip->addFile($file);

<?php
$zip->addFile($file_path, $filename);
?>
$files = "upload/".array('Dear GP.docx','ecommerce.doc');

Should be:应该是:

$files = array('upload/Dear GP.docx','upload/ecommerce.doc');

If you are still having issues then you should check if you have write permission to the current directory.如果您仍然遇到问题,那么您应该检查您是否对当前目录具有写权限。 You can check the return value of close() to check whether the file was actually written.你可以检查close()的返回值来检查文件是否真的被写入。

$res = $zip->close();
var_dump($res);

The output should be bool(true) if the write was successful.如果写入成功,输出应为bool(true)

Looks like you have a the wrong var name in the filesize() call also:看起来您在filesize()调用中也有错误的 var 名称:

header('Content-Length: ' . filesize($zipfilename));

Should probably be:应该是:

header('Content-Length: ' . filesize($zipname));

You could also add extra validation to check whether the files you are adding to the zip actually exist and before sending check the zip file exists.您还可以添加额外的验证来检查您添加到 zip 的文件是否实际存在,并在发送之前检查 zip 文件是否存在。

Edit: Turn on display errors to help you debug locally:编辑:打开显示错误以帮助您在本地调试:

ini_set('display_errors', 1);
error_reporting(E_ALL);

Answer is good but Please add these lines before header.答案很好,但请在标题前添加这些行。 Zip file is open in all zip software (winzip, winrar etc.) Zip 文件在所有 zip 软件(winzip、winrar 等)中打开

if (headers_sent()) 
    {
        // HTTP header has already been sent
        return false;
    }
// clean buffer(s)
while (ob_get_level() > 0)
    {
        ob_end_clean();
    }
 $zip = new ZipArchive;
        if ($zip->open('assets/myzip.zip',  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!';
       }

I got this code to download files from a folder.我得到了这个代码来从一个文件夹下载文件。

I have a client "download-all" button for files stored in a parallel directory on a webserver .我有一个客户端“全部下载”按钮,用于存储在网络服务器上的并行目录中的文件。 Having similar issues to the OP, the following code was created after reading many similar posts.与 OP 有类似的问题,在阅读了许多类似的帖子后创建了以下代码。

The server is running php7.4 on Ubuntu 20, don't forget to install your php's version of zip, mine being php7.4-zip.服务器在 Ubuntu 20 上运行 php7.4,不要忘记安装你的 php 版本的 zip,我的是 php7.4-zip。 The HTML uses Bootstrap 4.5.2 and font-awesome 5.13.0 HTML 使用 Bootstrap 4.5.2 和 font-awesome 5.13.0

<?php
if( isset( $_POST["downloadAll"] ) ){

    // all folders in remote dir are given a UID as a name
    $directory = "../remoteLinuxDirectory/" . $_SESSION["folderID"];
    $fileNames = scandir( $directory );
    
    // create new archive 
    $zip = new ZipArchive;

    // create a temporary file for zip creation
    $tmp_file = tempnam( $directory, $_SESSION["folderName"] );

    if( $zip->open( $tmp_file, ZipArchive::CREATE ) ){ 

        // $i = 0,1 show the dot and double dot directory in linux
        $i=2; 

        while( $i < count( $fileNames ) ){ 

           // addFile( 'from location', 'name of individual file')
           $zip->addFile( $directory . "/" . $fileNames[ $i ], $fileNames[ $i ] ); 
           $i++;
        }

        $zip->close();
    
        // remove special characters from the about-to-be-created zip filename 
        $cleanName = str_replace(array( ".",",","/","\\"," "),'', $_SESSION["folderName"])
        header("Content-disposition: attachment; filename=" . $cleanName . ".zip");
        header('Content-type: application/zip');

        // begin the zip download
        readfile( $tmp_file );

        // removes the temporary file created in the "../remoteLinuxDirectory/"
        unlink( $tmp_file );

    }else{
        // can be removed, but will dump some info incase the $zip->open fails
        var_dump( $tmp_file );
    }
}
?>

An HTML button:一个 HTML 按钮:

<form action="" method="post">
    <button class="btn btn-primary p-2 px-3">
        <input  name="downloadAll" value="1" hidden>
        <i class="fas fa-download"></i> Download All
    </button>
</form>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM