PhpSpreadsheet:权限 | ZipArchive::close(): 创建临时文件失败

Posted

技术标签:

【中文标题】PhpSpreadsheet:权限 | ZipArchive::close(): 创建临时文件失败【英文标题】:PhpSpreadsheet: Permissions | ZipArchive::close(): Failure to create temporary file 【发布时间】:2018-11-01 09:08:15 【问题描述】:

我想提供一个 Excel 文件以供使用 phpSpreadsheet 下载

这是我的代码:

    require 'vendor/autoload.php';

    use PhpOffice\PhpSpreadsheet\Spreadsheet;
    use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    $sheet->setCellValue('A1', 'Hello World !');

    $writer = new Xlsx($spreadsheet);
    $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');

    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment; filename="hello_world.xlsx"');
    $writer->save("php://output");

我收到以下错误消息:

    PHP Warning:  ZipArchive::close(): Failure to create temporary file: No such file or directory in /Users/sg/GitWorkingCopies/xxx1/xxx2/library/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php on line 374
    PHP Fatal error:  Uncaught exception 'PhpOffice\PhpSpreadsheet\Writer\Exception' with message 'Could not close zip file php://output.' in /Users/sg/GitWorkingCopies/xxx1/xxx2/library/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php:375

dokumentation of PHPSpreadsheet 说:

\PhpOffice\PhpSpreadsheet\Writer\Xlsx 在写入 php://output 时使用临时存储。默认情况下,临时文件存储在脚本的工作目录中。当无法访问时,它会回退到操作系统的临时文件位置。

upload_tmp_dir 是:/Applications/XAMPP/xamppfiles/temp/

我必须检查哪些文件夹权限? 或者是什么导致了问题?

【问题讨论】:

如果问题解决了,请accept您认为是您问题的最佳解决方案的答案,或者您可以提供和accept your own answer。 【参考方案1】:

PHP 中目录写入的一般规则:

一定存在

PHP进程可写,

open_basedirphp.ini 指令允许。

因此,在$writer->save() 方法中设置一些文件路径作为参数,并检查这三个规则是否满足。

如果您只想在 $writer->save() 方法中使用 php://outputphp://stdout 值,请检查以下规则:

1) sys_get_temp_dir() 函数返回的目录。在 Windows 中,sys_get_temp_dir() 默认返回当前操作系统用户的临时目录。该值可以通过sys_temp_dirphp.ini 指令更改。

2) upload_tmp_dir php.ini 指令返回的目录。 $useUploadTempDirectory 默认具有 false 值。要将其值设置为true,请在保存文件之前在代码中添加以下行:

\PhpOffice\PhpSpreadsheet\Shared\File::setUseUploadTempDirectory(true);


这里是负责选择保存路径的代码:

来自\PhpOffice\PhpSpreadsheet\Writer\Xlsx::save 方法(source):

// If $pFilename is php://output or php://stdout, make it a temporary file...
$originalFilename = $pFilename;
if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') 
    $pFilename = @tempnam(File::sysGetTempDir(), 'phpxltmp');
    if ($pFilename == '') 
        $pFilename = $originalFilename;
    

来自\PhpOffice\PhpSpreadsheet\SharedFile::sysGetTempDir 方法(source):

/**
 * Get the systems temporary directory.
 *
 * @return string
 */
public static function sysGetTempDir()

    if (self::$useUploadTempDirectory) 
        //  use upload-directory when defined to allow 
        // running on environments having very restricted open_basedir configs
        if (ini_get('upload_tmp_dir') !== false) 
            if ($temp = ini_get('upload_tmp_dir')) 
                if (file_exists($temp)) 
                    return realpath($temp);
                
            
        
    
    return realpath(sys_get_temp_dir());

【讨论】:

感谢您的回答。我明天会在办公室测试它。会给你反馈。非常感谢! 抱歉耽搁了。办公室里还发生了其他事情。所以这目前处于冰上。但我希望很快就会来。对不起。 有人可能会觉得这很有用:如果临时文件无法移动到其目的地,也会引发此错误。该消息可能有点混乱。 非常感谢。我已经尝试了一切,并且在这个问题上浪费了将近 3 个小时。最后“\PhpOffice\PhpSpreadsheet\Shared\File::setUseUploadTempDirectory(true);”这工作得很好【参考方案2】:

我不知道您的代码是否来自包含的文件,但我遇到了类似的问题。我尝试使用__DIR__ 常量并且它有效,我的代码如下所示:

$filepath = __DIR__ . "/reports/$filename_".date("Ymd_Gis").".xlsx";
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->save($filepath);

【讨论】:

【参考方案3】:

问题是 phpSpreadSheet 使用的 tmp 目录,PHP 进程无法写入该目录。我将 tmp 目录更改为上传 tmp 目录,现在问题已解决。我使用

解决了这个问题
\PhpOffice\PhpSpreadsheet\Shared\File::setUseUploadTempDirectory(true);

【讨论】:

以上是关于PhpSpreadsheet:权限 | ZipArchive::close(): 创建临时文件失败的主要内容,如果未能解决你的问题,请参考以下文章

PHPSpreadsheet - 如何从 PHPSpreadsheet 创建一个 zip 文件?

PHP 使用 PhpSpreadsheet

PHP 使用 PhpSpreadsheet

phpspreadsheet 中文文档 结构

PhpSpreadsheet的简单使用

PhpSpreadSheet 读写excel文件