PhpSpreadsheet:权限| ZipArchive :: close():无法创建临时文件

时间:2018-05-22 14:35:03

标签: php phpspreadsheet phpoffice

我想提供一个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://输出时使用临时存储。默认情况下,临时文件存储在脚本的工作目录中。当没有访问权限时,它会回退到操作系统的临时文件位置。

upload_tmp_dir为:/Applications/XAMPP/xamppfiles/temp/

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

3 个答案:

答案 0 :(得分:4)

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

必须存在

可以通过PHP进程写入

open_basedir php.ini指令允许这样做。

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

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

1)sys_get_temp_dir()函数返回的目录。在Windows sys_get_temp_dir()中默认返回当前OS用户的临时目录。可以通过sys_temp_dir php.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());
}

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

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