【问题标题】:PHP Dynamically Generated Zip File by ZipArchive Can't be Opened无法打开 ZipArchive 的 PHP 动态生成的 Zip 文件
【发布时间】:2014-05-15 02:32:07
【问题描述】:

我正在尝试创建用户上传图像的 zip 文件,当用户单击按钮时将生成该文件以供下载。该按钮位于 Wordpress 管理员的页面上。该页面来自添加新管理部分的插件。单击按钮时,它会将表单提交到“themes/twentyfourteen/page-templates”目录中的页面。该页面名为 cartoon_zip.php,是通过管理中的 Pages 部分创建的,因此它的 url 为 http://www.sitename.com/cartoon-zip/。当我单击该文件时,它似乎可以工作。没有错误发生,并出现一个保存文件对话框。我将文件保存在本地并尝试解压缩,但收到消息“无法使用此程序提取文件“characters.zip”的内容。”我在 Mac 上,所以是 The Unarchiver 试图打开;它也不能在 PC 上运行。下面是我正在使用的代码;非常感谢任何帮助。

<?php 
    /*
        Template name: Cartoon Zip
    */

    if(isset($_REQUEST['order_id'])){
        $order_id = $_REQUEST['order_id'];

        $query = "SELECT optional_image FROM order_listing WHERE order_no = '".$order_id."'";
        $query2 = "SELECT main_image FROM character_order WHERE order_id = '".$order_id."'";

        $entries = $wpdb->get_results($query);
        $entries2 = $wpdb->get_results($query2);

        $error = "";        //error holder

        if(extension_loaded('zip')){    // Checking ZIP extension is available

            $zip = new ZipArchive();            // Load zip library 
            $zip_name = "characters.zip";           // Zip name

            if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){       // Opening zip file to load files
                $error .=  "* Sorry ZIP creation failed at this time<br/>";
            }

            foreach( $entries as $entry ) {
                $image=$entry->optional_image; 
                if(!empty($image)):
                    $url = 'wp-content/themes/twentyfourteen/upload/main/'.$image;
                    if(file_exists($url)){
                        $zip->addFile($url,$image);         // Adding files into zip
                    }
                endif;
            }
            foreach( $entries2 as $entry ) {
                $image=$entry->main_image; 
                if(!empty($image)):
                    $url = 'wp-content/themes/twentyfourteen/upload/character/'.$image;
                    if(file_exists($url)){
                        $zip->addFile($url,$image);         // Adding files into zip
                    }
                endif;
            }

            if ($zip->close() === false) {
                exit("Error creating ZIP file");
            };

            $filename = $zip_name;
            // send $filename to browser
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mimeType = finfo_file($finfo, $filename);
            $size = filesize($filename);
            $name = basename($filename);

            if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
                // cache settings for IE6 on HTTPS
                header('Cache-Control: max-age=120');
                header('Pragma: public');
            } else {
                header('Cache-Control: private, max-age=120, must-revalidate');
                header("Pragma: no-cache");
            }
            header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // long ago
            header("Content-Type: $mimeType");
            header('Content-Disposition: attachment; filename="' . $name . '";');
            header("Accept-Ranges: bytes");
            header('Content-Length: ' . filesize($filename));

            readfile($fullFilePath);
            exit;
        }else
            $error .= "* You dont have ZIP extension<br/>";
    }
?>

编辑:所以我设法通过下面的组合 doublesharp 的帮助以及将标题更改为以下内容来解决这个问题。

$file = $zip_name;
        if (file_exists($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename='.basename($file));
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            ob_clean();
            flush();
            readfile($file);
            exit;
        }

这是完整的工作代码。

<?php 
/*
    Template name: Cartoon Zip
*/

if(isset($_REQUEST['order_id'])){
    global $wpdb;
    $order_id = isset( $_REQUEST['order_id'] )? $_REQUEST['order_id'] : 0;

    $query = $wpdb->prepare( "SELECT optional_image FROM order_listing WHERE order_no = %s", $order_id );
    $query2 = $wpdb->prepare( "SELECT main_image FROM character_order WHERE order_id = %s", $order_id );

    $entries = $wpdb->get_results($query);
    $entries2 = $wpdb->get_results($query2);

    $error = "";        //error holder

    if(extension_loaded('zip')){    // Checking ZIP extension is available

        $zip = new ZipArchive();            // Load zip library 
        $zip_name = "characters.zip";           // Zip name

        if($zip->open($zip_name, ZIPARCHIVE::CREATE)!==TRUE){       // Opening zip file to load files
            $error .=  "* Sorry ZIP creation failed at this time<br/>";
        }

        foreach( $entries as $entry ) {
            $image=$entry->optional_image; 
            if( ! empty( $image ) ){
                $filename = WP_CONTENT_DIR.'/themes/twentyfourteen/upload/main/'.$image;
                if ( file_exists( $filename ) ){
                    // Adding files into zip
                    $zip->addFile( $filename, $image );
                }
            }
        }
        foreach( $entries2 as $entry ) {
            $image=$entry->main_image; 
            if( ! empty( $image ) ){
                $filename = WP_CONTENT_DIR.'/themes/twentyfourteen/upload/character/'.$image;
                if ( file_exists( $filename ) ){
                    // Adding files into zip
                    $zip->addFile( $filename, $image );
                }
            }
        }

        if ($zip->close() === false) {
            exit("Error creating ZIP file");
        };

        $file = $zip_name;
        if (file_exists($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename='.basename($file));
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            ob_clean();
            flush();
            readfile($file);
            exit;
        }
    }else
        $error .= "* You dont have ZIP extension<br/>";
}
?>

【问题讨论】:

  • 你有一个 SQL 注入漏洞,你应该在你的 SQL 中使用 $wpdb-&gt;prepare() on $order_id
  • 感谢您指出这一点。我通常不使用 PHP 或 Wordpress。

标签: php wordpress download ziparchive


【解决方案1】:

addFile() 的第一个参数需要是图像的完整路径,但您使用的是带有 wp-content/... 的相对路径。此页面的模板很可能在您的wp-content/themes/ 目录中,因此对file_exists() 的调用失败,这意味着没有任何内容传递给ZipArchive。 WordPress 提供了一个常量,其中包含名为 WP_CONTENT_DIRwp-content 文件夹的绝对路径 - 或者如果您不确定您将使用什么主题,您可以使用 get_template_directory()

使用WP_CONTENT_DIR:

if( ! empty( $image ) ){
    $filename = WP_CONTENT_DIR.'/themes/twentyfourteen/upload/character/'.$image;
    if ( file_exists( $filename ) ){
        // Adding files into zip
        $zip->addFile( $filename, $image );
    }
}

使用get_template_directory()

$filename = get_template_directory().'/upload/character/'.$image;

SQL 注入警告

您还有一个 SQL 注入漏洞,可以在请求的order_id 中传递任意 SQL。使用$wpdb-&gt;prepare() 进行防护。

global $wpdb;
$order_id = isset( $_REQUEST['order_id'] )? $_REQUEST['order_id'] : 0;
$query = $wpdb->prepare( "SELECT optional_image FROM order_listing WHERE order_no = %s", $order_id );
$query2 = $wpdb->prepare( "SELECT main_image FROM character_order WHERE order_id = %s", $order_id );

【讨论】:

  • 感谢您的帮助;和安全提示。我进行了您建议的更改,但我仍然无法打开创建的文件。我知道图像的路径是正确的,但我不确定还有什么问题。您对可能出现的问题还有其他想法吗?
  • 很难说没有亲眼看到它 - 也许尝试使用 ZipArchive 打开它或只列出内容?文件大小是否非零?
  • 所以,我将其更改为只是回显$filename,然后我得到了从服务器根目录开始的正确路径。这是它需要的路径。我还在浏览器中输入了以 wp-content 目录开头的路径,所有文件都位于代码生成的位置。文件大小通常是 400 KB,但是当我在本地存档图像时,它是 1.2 MB。接下来我将使用 ZipArchive 打开存档并列出其内容。
  • 我能够成功打开文件并将其解压缩到单独的目录中。所以我尝试再次运行下载部分,文件大小似乎是正确的,Unarchiver 现在确实运行了,但创建了一个名为 characters.zip.cpgz 的文件,而不是其中包含图像的文件夹。你认为这可能是标题部分的问题吗?
  • 我会在最后使用$zip_nameunlink() 的绝对路径,以确保您不会以冲突告终(即使这样两个请求可能同时结束最多写入同一个 ZIP 文件)。将'Content-Type' 设置为'application/zip'(或者动态设置内容类型)。如果这不起作用,请写信给error_log() 进行调试,并确保每个步骤都使用正确的路径执行您期望的操作,等等。
猜你喜欢
  • 2016-03-08
  • 1970-01-01
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-13
相关资源
最近更新 更多