PHP ZipArchive isn't creating a gs:// zip file in Google AppEngine, Warning: filesize(): stat failed for gs://

I'm able to directly write and read files in Google Storage, but when I try to use ZipArchive to create a file, it fails. Google says that the zip extension is enabled in the GAE.

$tmpdirectory .= 'gs://#default#/tmp/user-'.$uid;
$uniqueid = uniqid() . time();
$user_visible_filename = '';
$output_path = sprintf("%s/", $tmpdirectory, $uniqueid);

$zip = new ZipArchive;
$res = $zip->open($output_path, ZipArchive::CREATE);
if ($res === true) {
    foreach ($data as $datatype => $records) {
        $filename = sprintf("%s/%s.csv", $tmpdirectory, $datatype);
        write_csv_to_filename($records, $filename);     
        $localname = basename($filename);
        $fileresult = $zip->addFromString($localname, file_get_contents($filename));
        print "adding $localname... num files in zip: ".($fileresult ? "true" : "false")." -> ".$zip->numFiles."<br/>\n";

$closeresult = $zip->close();
print "user_visible_filename: $user_visible_filename<br/>\n";
print "zip filename: $output_path<br/>\n";
print "file size: ".filesize($output_path)."<br/>\n";

header('Content-Type: application/zip');
header('Content-Length: '.filesize($output_path));
header('Content-Disposition: attachment; filename=' . $user_visible_filename);

The above code writes some csv files and I want to bundle them together in a zip file and have their browser download it. I know that the above headers() won't work because I'm printing stuff about before them; I'm going printing the stuff out to debug what's going wrong.

I am able to write each of the CSVs to gs:// and I'm able to access their correct filesize and read their contents back after writing them.

However, when I try to read the filesize() of the zip file (gs://#default#/tmp/user-152/ it craps out with a big warning message (cannot stat file) and stack trace as if the file doesn't exist.

$zip->close(); returns false which means there was a failure, but I have no idea why it failed.

1 answer

  • answered 2018-07-11 19:06 Kenny Wyland

    I found an alternative solution that worked: TbsZip

    require_once '../inc/tbszip.php';
    $tmpfile = tempnam('/tmp', 'export');
    $zip = new clsTbsZip();
    foreach ($data as $datatype => $records) {
        $filename = sprintf("%s/%s.csv", $tmpdirectory, $datatype);
        write_csv_to_filename($records, $filename);
        $localname = basename($filename);
        //$fileresult = $zip->addFile($filename, $localname);
        $zip->FileAdd($localname, file_get_contents($filename), TBSZIP_STRING);
    // Flush() will send all the required headers for downloading the file.
    $zip->Flush(TBSZIP_DOWNLOAD, $user_visible_filename, 'application/zip');