php zip压缩包下载

说明
实现效果:使用php压缩目标目录成zip文件,并下载
环境框架:laravel 5.1 php 5.6
示例
逻辑处理片段代码:

use ZipArchive;//此处需要引入ZipArchive类
/**
 * 文件夹打包下载
 * @param Request $request
 */
public function Down(Request $request) {
    //判断zip扩展类是否加载
    if ( ! extension_loaded('zip')) {
        return Redirect::back();
    }
    set_time_limit(0);
    $iId = $request->get('id');
    //获取需要压缩的文件路径
    $aResArr = Compress::getTargetDirectory($iId);
    if ($aResArr === false || $aResArr['sDir'] == '') {
        return Redirect::back();
    }

    //生成压缩包
    $oZip = new ZipArchive();
    //压缩包命名
    $sZipName = md5(uniqid() . time()) . '.zip';
    //将一级目录名作为下载压缩包名
    $sFileName = $aResArr['sFileName'] ? $aResArr['sFileName'] . '.zip' : $sZipName;
    $sRes = $oZip->open($sZipName, ZipArchive::OVERWRITE | ZipArchive::CREATE);
    if($sRes === true) {
        //压缩目标目录
        Compress::compressTargetDirectory($aResArr['sDir'], $oZip);
        $oZip->close();
    }

    //下载压缩包
    header('Content-Type:application/zip');
    if (preg_match("/MSIE/", $_SERVER["HTTP_USER_AGENT"])) {
        header('Content-Disposition: attachment; filename="' . rawurlencode($sFileName) . '"');
    } else if (preg_match("/Firefox/", $_SERVER["HTTP_USER_AGENT"])) {
        header('Content-Disposition: attachment; filename*="utf8\'\'' . $sFileName . '"');
    } else {
        header('Content-Disposition: attachment; filename="' . $sFileName . '"');
    }
    header('Content-Length:' . filesize($sZipName));
    session_write_close();
    readfile($sZipName);
    ob_flush();
    flush();
    //删除生成的目标目录
    Compress::removeTargetDirectory($aResArr['sDir']);
    //删除生成的压缩包
    unlink($sZipName);
}

操作类代码(compress.php):

<?php
/**
 * 文件压缩类
 */

namespace App\Services;

use App\File;
use Illuminate\Support\Facades\DB;

class Compress
{
    /**
     * 获取文件信息
     * @param $iId
     * @return bool
     */
    public static function getFileInfo($iId)
    {
        if ( ! $iId) {
            return false;
        }
        return File::select('id', 'name', 'isdir', 'loc')
            ->where('id', $iId)
            ->first();
    }

    /**
     * 获取指定文件夹下所有信息
     * @param $iId
     * @return bool
     */
    public static function getFileInfoById($iId)
    {
        if ( ! $iId) {
            return false;
        }
        $aConditions = [':path' => '%/' . $iId . '/' . '%'];
        $sSql = 'SELECT * FROM `File` WHERE `path` LIKE :path';
        return DB::select($sSql, $aConditions);
    }

    /**
     * 创建目标目录或文件
     * @param $sName 目标目录或名称
     * @param $sPath 目标目录路径
     * @param int $iStatus 目录类型 0 文件 1 文件夹名称
     * @param string $sPrev 上级目录路径
     * @return bool|string
     */
    public static function createDirectory($sName, $sPath, $iStatus = 0, $sPrev = '')
    {
        if ( ! defined('COM_DIR') ) {
            define('COM_DIR', storage_path('upload/compress'));
        }
        if ( ! defined('UP_DIR') ) {
            define('UP_DIR', storage_path('upload/files'));
        }
        if ( ! defined('DS')) {
            define('DS', DIRECTORY_SEPARATOR);
        }
        $newDir =  $sPrev ?: COM_DIR . DS . md5(uniqid());
        if ($iStatus == 0) {//文件
            $sExt = self::getExtByPath(trim($sPath));
            $sFileName = $sName ? basename($sName, '.' . self::getExtByPath(trim($sName))) . '.' . $sExt : basename($sPath);
            $newPath = $newDir . DS . $sFileName;
            //判断文件是否存在
            if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
                $newPath = iconv('utf-8', 'gbk//IGNORE', $newPath);
            }
            //文件不存在
            if ( ! file_exists($sPath)) {
                return false;
            }
            //文件夹不存在,创建文件夹
            if ( ! file_exists($newDir)) {
                mkdir($newDir, 0777, true);
            }
            //copy原有文件到新目录
            if ( ! copy($sPath, $newPath)) {
                return false;
            }
        } else {//文件夹
            if ( ! $sName) {
                return false;
            }
            $newPath = $newDir . DS . $sName;
            //判断文件是否存在
            if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
                $newPath = iconv('utf-8', 'gbk//IGNORE', $newPath);
            }
            //文件夹不存在,创建文件夹
            if ( ! file_exists($newPath)) {
                mkdir($newPath, 0777, true);
            }
        }
        return $newPath;
    }

    /**
     * 获取目标目录路径
     * @param $iId 目标id
     * @param string $sPrev 上级目录路径
     * @return array|bool
     */
    public static function getDirectory($iId, $sPrev = '')
    {
        $sDir = '';
        $sFileName = '';
        //获取目标文件信息
        $aFile = self::getFileInfo($iId);
        if (count($aFile) < 1) {
            return false;
        }
        //创建目标目录路径
        $sPath = self::createDirectory($aFile->name, $aFile->loc, $aFile->isdir ? 1 : 0, $sPrev);
        //目标目录路径,与文件名获取
        if ($sPrev == '') {
            $sDir = $sPath ?: '';
            $sFileName = $aFile->isdir ? $aFile->name : basename($aFile->name, '.' . self::getExtByPath(trim($aFile->name)));
        }
        //循环文件夹,生成子目录
        if ($aFile->isdir == 1) {//文件夹
            $aList = self::getFileInfoById($aFile->uid, $aFile->id);
            if (count($aList) > 0) {
                foreach ($aList as $v) {
                    self::getDirectory($v->id, $sPath);
                }
            }
        }
        return [
            'sDir' => $sDir,
            'sFileName' => $sFileName
        ];
    }

    /**
     * 压缩目标目录
     * @param $sDir 目标目录路径
     * @param $aZip ZipArchive类对象
     * @param string $sPrev 上级目录路径
     * @return null
     */
    public static function compressDirectory($sDir, $aZip, $sPrev = '')
    {
        $sBasename = basename($sDir);//文件(夹)名
        $sBasePath = $sPrev ? $sPrev . '/' . $sBasename : $sBasename;//目标根目录
        if(is_dir($sDir)) {
            $oHandler = opendir($sDir);
            $aZip->addEmptyDir($sBasePath);
            while ($oFile = readdir($oHandler)) {
                $sRealPath = $sDir . '/' . $oFile;
                if (is_dir($sRealPath)) {
                    if ($oFile !== '.' && $oFile !== '..') {
                        $aZip->addEmptyDir($sBasePath . '/' . $oFile);
                        self::compressDirectory($sRealPath, $aZip, $sBasePath);
                    }
                } else {
                    $aZip->addFile($sRealPath, $sBasePath . '/' . $oFile);
                }
            }
            closedir($oHandler);
        } else {
            $aZip->addFile($sDir, $sBasePath);
        }
        return null;
    }

    /**
     * 删除生成的目标目录
     * @param $sDir
     */
    public static function removeDirectory($sDir)
    {
        //获取包含目标目录的上级目录路径
        $sDir = str_replace('\\' . basename($sDir), '', $sDir);
        //判断当前目录类型
        if (is_dir($sDir)) {
            $oHandler = opendir($sDir);
            while ($oFile = readdir($oHandler)) {
                $sRealPath = $sDir . '/' . $oFile;
                if (is_dir($sRealPath)) {
                    if ($oFile !== '.' && $oFile !== '..') {
                        self::removeDirectory($sRealPath);
                    }
                } else {//删除文件
                    unlink($sRealPath);
                }
            }
            closedir($oHandler);
            rmdir($sDir);
        } else {
            unlink($sDir);
        }
    }

    /**
     * 获取文件后缀
     * @param $sPath
     */
    public static function getExtByPath($sPath){
        $sUrl = parse_url($sPath); // 解析url 返回其组成部分
        return pathinfo($sUrl['path'], PATHINFO_EXTENSION); //返回文件扩展名信息
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值