web-dev-qa-db-ja.com

「Zipファイルphp:// outputを閉じることができませんでした」というメッセージを含むPHPExcel_Writer_Exception

PHPExcelを使用して、Excelファイルでユーザーにデータをエクスポートしています。スクリプトを作成してすぐにExcelファイルをユーザーに送信したいと思います。これが私のテストコードです。

_try{

  /* Some test data */
  $data = array(
    array(1, 10   , 2             ,),
    array(3, 'qqq', 'some string' ,),
  );

  $objPHPExcel = new PHPExcel();
  $objPHPExcel->setActiveSheetIndex(0);

  /* Fill the Excel sheet with the data */
  $rowI = 0;
  foreach($data as $row){
    $colI = 0;
    foreach($row as $v){
      $colChar = PHPExcel_Cell::stringFromColumnIndex($colI++);
      $cellId = $colChar.($rowI+1);
      $objPHPExcel->getActiveSheet()->SetCellValue($cellId, $v);
    }
    $rowI++;
  }

  header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  header('Content-Disposition: attachment;filename="export.xlsx"');
  header('Cache-Control: max-age=0');

  $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
  $objWriter->save('php://output');

}catch(Exception $e){
  echo $e->__toString();
}
_

ローカルサーバーで_(Windows 7 x64, Php 5.3.8, Apache 2.2.21)_有効なxlsxファイルを取得します。エラーはありません。しかし、ライブサーバー_(Linux 2.6.32-5-AMD64, PHP 5.3.3-7+squeeze13, Apache 2.2.16)_に問題があります。このスクリプトにより、ブラウザはそのようなコンテンツを含む「export.xlsx」ファイルをダウンロードできます。

_exception 'PHPExcel_Writer_Exception' with message 'Could not close Zip file php://output.' in /var/www/someuser/data/www/somedomain.com/libs/PHPExcel/Writer/Excel2007.php:348
Stack trace:
#0 /var/www/someuser/data/www/somedomain.com/classes/Report/Leads/Export.php(339): PHPExcel_Writer_Excel2007->save('php://output')
#1 /var/www/someuser/data/www/somedomain.com/application/pages/account/controllers/TestController.php(13): Report_Leads_Export->Test()
#2 /var/www/someuser/data/www/somedomain.com/libs/Zend/Controller/Action.php(516): Account_TestController->indexAction()
#3 /var/www/someuser/data/www/somedomain.com/libs/Zend/Controller/Dispatcher/Standard.php(295): Zend_Controller_Action->dispatch('indexAction')
#4 /var/www/someuser/data/www/somedomain.com/libs/Zend/Controller/Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#5 /var/www/someuser/data/www/somedomain.com/index.php(511): Zend_Controller_Front->dispatch()
#6 {main}
_

PHPはセーフモードで実行されていません。 「open_basedir」オプションは空です(コメント化されています)。

PHPExcelファイルでそのようなコードを見つけました。

_if ($objZip->close() === false) {
    throw new PHPExcel_Writer_Exception("Could not close Zip file $pFilename.");
}
_

そのため、問題の理由は$objZip->close() === falseで、ここで_$objZip_はZipArchiveクラスのインスタンスです。

問題の理由は何ですか?また、どうすれば解決できますか?ありがとうございました。

26
Pavel L

Php:// outputに保存する際のこのエラーの最も一般的な原因は、有効なシステムの一時フォルダーを含まないopen_basedirの制限です(例:/tmp)、またはシステムのtempフォルダーのアクセス許可... suhosinは、明らかなアクセス許可が正しく設定されているように見える場合でも、これに影響を与える可能性があります。

可能な回避策は、ファイルを書き込むための完全な権限があることがわかっているディレクトリのファイルシステムにファイルを書き込み、readfile()を使用してそのファイルをphp:// outputにストリーミングしてからファイルを削除することです

38
Mark Baker

Mark Ba​​kerに感謝します。彼の答えは問題を解決しました。私は彼のアプローチを使用して簡単なヘルパーメソッドを作成しました。

_static function SaveViaTempFile($objWriter){
    $filePath = sys_get_temp_dir() . "/" . Rand(0, getrandmax()) . Rand(0, getrandmax()) . ".tmp";
    $objWriter->save($filePath);
    readfile($filePath);
    unlink($filePath);
}
_

そして、$objWriter->save('php://output')SaveViaTempFile($objWriter)に置き換えたところです。

25
Pavel L

こんにちは私は次のことを試しました:サーバーlinux Centos 7.0では、ディレクトリtmpのルートを指定しないで、入力します:

function SaveViaTempFile($objWriter){
    $filePath = '' . Rand(0, getrandmax()) . Rand(0, getrandmax()) . ".tmp";
    $objWriter->save($filePath);
    readfile($filePath);
    unlink($filePath);
    exit;
}

そして仕事!!

優れた友人PHP 7.1.2で作業し、PhpSpreadsheetで作業し、同じファイルを修正します。

PhpSpreadsheet/Writer/Excel2007.php

ソリューションは、Excel2007.phpに保存されています

if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
    $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp');

2行目を次のように置き換えます。

$pFilename = dirname(__FILE__).'/'. Rand(0, getrandmax()) . Rand(0, getrandmax()) . ".phpxltmp";

ありがとう。

2
blackslifer888

これと同じエラーメッセージが表示される場合があるのは、保存しようとしているファイル名が実際にExcelで既に開いているためである可能性があります。

2
Custam

Phpファイルを実行しようとしても同じエラーが発生しました。次の行を変更してください。

$objWriter->save("/dir1"."/".$file.".xlsx");

このため:

$objWriter->save(dirname(__FILE__)."/dir1"."/".$file.".xlsx");

dirパスを追加すると、機能しました!!!。

1

このエラーは、存在しないフォルダーにファイルを保存しようとしたときにも発生します。パス全体が存在することを確認してください。

0
Joey Quint

私の場合、ターゲットフォルダーのアクセス許可をrwxrwxrwx(0777)に変更し、動作するようになりました!

0

そして、私の答えは次のとおりです。ファイル名には「:」、「、」、「」などの記号がありました。それらを別のものに置き換える必要がありました。

0
Velaro