简体   繁体   中英

Downloaded zip archive empty after adding csv file

Can skip About and Goal if necessary. They provide context/background about program.


When I download a zip archive that is supposed to have a csv file in it, I get an empty archive or invalid archive. Now, I can make the zip archive with the csv in it, on the server and download via FileZilla. This is not the desired use case. User wants to download automatically after clicking a button.


Agents sign up for event (ie RSVP to it) and provide a set of photos. For every agent, there are +1 photos. User wants to download a list of all RSVPs for each event (ie the sign up data). For each RSVP, User also wants to see the photos they uploaded to the server.


  1. Create csv file on server of mysql query (each row is an RSVP)
  2. For each row, create zip archive for that row's/RSVP's photos.
  3. Wanted: 1 csv file and multiple zip archives all in one big archive
  4. End result: Add all files into one zip archive and download to User.
  5. Addendum: This big zip file needs to be freshly generated every time it is requested.


CSV file created. Below it is added to ZipArchive object. Downloaded zip file and found it .

//store the result of the query. Included to show process
$result = mysqli_query($dbh, $sql);
//open the file to write the information to.
$file = fopen('event-report.csv', 'w');
$txt .= 'Title Company,' .'Event ID,' . 'Event Time,' . 'First Name,' . 'Last Name,' . 'Email,' . 'Agent Company,' . 'Phone Number,' . 'Listing ID,' . 'URL,' . 'Address,' . 'ZIP,' . "\n";
while ($row = mysqli_fetch_row($result)){
    for ($i=0; $i<12; $i++){
        $txt .= $row[$i] . ',';             //About the agent attending
    }
    $txt .= "\n";
    $listings[$listing_count] = $row[8];    
}
fputs($file, $txt); //store into csv file
fclose($file);        //verified on server; contains desired output

$zip = new ZipArchive();
$dir = 'tmp';                  //create temporary directory with write access
if ( !file_exists($dir) ) {
    mkdir ($dir, 0755);        //Everything for owner, read/execute for others
}
if($zip->open('test.zip', ZIPARCHIVE::CREATE) === TRUE ){

    $zip->addFile('event-report.csv');
    if (file_exists($zip->getFromName('event-report.csv'))){
        echo "Exists";
    }
    else{
        echo "Does Not Exist";
        echo $_SERVER['DOCUMENT_ROOT'];
    }
}
else {
    echo "Failed code";
}
$zip->close();
if(!$return){
    echo " You do not have write access to current folder.";
}
else{
    echo "You do have access.";  //without headers, the zip containing csv successfully created on server.
}

header('Content-disposition: attachment; filename=download.zip');
header('Content-type: application/zip');
readfile($dir.'/test.zip');     //When downloaded: still empty/invalid.


  1. Zip is not finding the file because it is being created at the same time.
    1a. :. :。 Files created can be put into zip archive right after closing.
  2. addFile parameter(s) are incorrect or lacking.
    2a. Man page says for this parameter: "path to the file to add"
    2b. Tried putting the path after the domain name but no success:
    $zip->addFile('/f1/f2/f3/f.csv');
    2c. PHP Manual > ZipArchive::addFile
      i. : The parameter is just the name of the file. :参数只是文件名。 No path is needed in this case.

  1. How do I add a csv file, a zip archive, or any file in general to another zip archive so that it will not be empty when I download it?
  2. Is this implementation incorrect because I am trying to add a file to a zip archive right after creating it? See
  3. If this question can be solved by a little reading, then what resources can you link that can guide me along? I have spent an entire day reading in regards to this issue and do not feel like I understand what I am missing here.
    3a. file permissions

添加到归档文件时,您必须使用绝对路径来明确显示。

$zip->addFile($abs_path, $relative_path); 

Solution: flush headers before calling readfile(). I learned that I do not need flush() but I left it in there anyways. See SO post that helped me include these two statements here

header('Content-type: application/zip');
header('Content-disposition: attachment; filename=test.zip');
ob_clean();   // discard any data in the output buffer (if possible)
flush();      // flush headers (if possible)
readfile('tmp/test.zip');
exit();

I also changed some minor things with the error checking that I thought I would mention below:
I made a directory with certain permissions that will hold the files I want to put into the archive. This is done at the beginning before the csv and zip are created.

$dir = 'tmp/';
if ( !file_exists($dir) ) {
    mkdir ($dir, 0777);
}

Opening the file has changed too. It now involves the new directory I make:

$zip = new ZipArchive;
if($zip->open($dir.'test.zip', ZIPARCHIVE::CREATE) === TRUE ){

    $res = $zip->addFile('tmp/event-report.csv', 'event-report.csv');                           //add the report csv file.
    if ($res){
        echo "Exists ";
    }
    else{
        echo "Does Not Exist ";
        //echo $_SERVER['DOCUMENT_ROOT'];
    }
}

Thanks to everyone that contributed or just viewed this question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM