How to zip a folder and download it using php?

前端 未结 5 2128
伪装坚强ぢ
伪装坚强ぢ 2020-12-15 15:01

I have folder named \"data\". This \"data\" folder contains a file \"filecontent.txt\" and another folder named \"Files\". The \"Files\" folder contains a \"info.txt\" file.

5条回答
  •  無奈伤痛
    2020-12-15 15:45

    I had to do the same thing a few days ago and here is what I did.

    1) Retrieve File/Folder structure and fill an array of items. Each item is either a file or a folder, if it's a folder, retrieve its content as items the same way.

    2) Parse that array and generate the zip file.

    Put my code below, you will of course have to adapt it depending on how your application was made.

    // Get files
    $items['items'] = $this->getFilesStructureinFolder($folderId);
    
    $archiveName = $baseDir . 'temp_' . time(). '.zip';
    
    if (!extension_loaded('zip')) {
        dl('zip.so');
    }
    
    //all files added now
    $zip = new ZipArchive();
    $zip->open($archiveName, ZipArchive::OVERWRITE);
    
    $this->fillZipRecursive($zip, $items);
    
    $zip->close();
    
    //outputs file
    if (!file_exists($archiveName)) {
        error_log('File doesn\'t exist.');
        echo 'Folder is empty';
        return;
    }
    
    
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private", false);
    header("Content-Type: application/zip");
    header("Content-Disposition: attachment; filename=" . basename($archiveName) . ";" );
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: " . filesize($archiveName));
    readfile($archiveName);
    
    //deletes file when its done...
    unlink($archiveName);
    

    Methods used to fill & parse:

    /**
     * 
     * Gets all the files recursively within a folder and keeps the structure.
     * 
     * @param   int     $folderId   The id of the folder from which we start the search
     * @return  array   $tree       The data files/folders data structure within the given folder id
     */
    public function getFilesStructureinFolder($folderId) {
        $result = array();
    
        $query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND status = 1 AND parent_folder_id = ? ORDER BY name ASC', $folderId);
    
        $folders = $query->result();
    
        foreach($folders as $folder) {
            $folderItem = array();
            $folderItem['type']     = 'folder';
            $folderItem['obj']      = $folder;  
            $folderItem['items']    = $this->getFilesStructureinFolder($folder->id);
            $result[]               = $folderItem;
        }
    
        $query = $this->db->query('SELECT * FROM xx WHERE deleted = 0 AND xx = ? AND status = 1 ORDER BY name ASC', $folderId);
    
        $files = $query->result();
    
        foreach ($files as $file) {
            $fileItem = array();
            $fileItem['type']   = 'file';
            $fileItem['obj']    = $file;    
            $result[]           = $fileItem;
        }
    
        return $result;
    }
    
    /**
     * Fills zip file recursively
     * 
     * @param ZipArchive    $zip        The zip archive we are filling
     * @param Array         $items      The array representing the file/folder structure
     * @param String        $zipPath    Local path within the zip
     * 
     */
    public function fillZipRecursive($zip, $items, $zipPath = '') {
        $baseDir = $this->CI->config->item('xxx');
    
        foreach ($items['items'] as $item) {
    
            //Item is a file
            if ($item['type'] == 'file') {
                $file = $item['obj'];
                $fileName = $baseDir . '/' . $file->fs_folder_id . '/' . $file->file_name;
    
                if (trim($file->file_name) == '' || !file_exists($fileName))
                    continue;
    
                $zip->addFile($fileName, $zipPath.''.$file->file_name);
            }
    
            //Item is a folder
            else if ($item['type'] == 'folder') {
                $folder     = $item['obj'];
    
                $zip->addEmptyDir($zipPath.''.$folder->name);
    
                //Folder probably has items in it!
                if (!empty($item['items']))
                    $this->fillZipRecursive($zip, $item, $zipPath.'/'.$folder->name.'/');
            }
        }
    } 
    

提交回复
热议问题