您现在的位置是:首页 > 技术教程 正文

PHP - ZipArchive上传、下载、兼容win乱码实例

admin 阅读: 2024-04-30
后台-插件-广告管理-内容页头部广告(手机)

概述

在很多实际生产场景都需要批量上传、下载一些文件的处理,整理了使用PHP语言操作ZipArchive实践和实例,ZipArchive需要服务器上安装zlib库,php扩展中安装zip扩展。

服务器环境扩展

ZipArchive类库的PHP版本要求如下,另外php需要查看是否已经成功安装zip扩展,服务器上需要安装zlib包,具体查看方法在下面的代码段里。

# ZipArchive 类版本要求,来自官网
# (PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL zip >= 1.1.0)

#查看是否安装zlib包
yum list installed | grep zlib


php-fpm -m | grep zip
zip

$zipVersion = phpversion('zip');
echo "Zip Extension Version: " . $zipVersion.PHP_EOL;

# 输出结果 
# Zip Extension Version: 1.15.6

实践

ZipArchive类,使用范围非常丰富,这篇博客里主要介绍上传和下载功能,先整理下载的实践实例,有几点需要特别注意的点:

  • 目录和文件的权限,包括复制的源文件和目标文件
  • 移动的文件夹一定要存在
  • ZipArchive扩展所需要的zlib和zip扩展,注意版本的差异性

文件下载

文件下载相对比较容易,先创建一个空的zip包,在把需要压缩的文件添加进zip包里。

//压缩包生成的路径,最后文件添加在这个zip包中
$destination = '/home/wwwroot/testDemo.zip';

if (!file_exists(dirname($destination))) {
    mkdir(dirname($destination), 0777, true);
}

$zip = new ZipArchive;
if ($zip->open($destination, ZIPARCHIVE::CREATE) !== true) {
    echo '服务器错误'.PHP_EOL;
}

$filePath = '/server_images/data/劳务派遣协议.pdf';

$fileSuffix = pathinfo($filePath,PATHINFO_EXTENSION); // 输出 pdf
$fileName = pathinfo($filePath, PATHINFO_FILENAME);   // 输出 劳务派遣协议
$rename = 'stark_' . $fileName.'.'.$fileSuffix; //新名字

#把路径$filePath 生成到zip包中,$rename是新的文件名
$zip->addFile($filePath,  $rename );

# 创建目录的路径
$createPathName = '';
$zip->addEmptyDir($createPathName);
$zip->close();

$strFile = '劳务派遣协议.zip';
header("Content-type:application/zip");
header("Content-Disposition:attachment;filename=" . $strFile);
readfile($destination);

文件上传

文件上传相对比较麻烦,首先要把文件移动到指定的目录下,demo中的例子是$file_path

$file_path = '/home/wwwroot/upload/';
if (!is_dir(dirname($file_path))) {
    mkdir(dirname($file_path), 0777, true);
}
//把文件移动到$file_path目录里
if( is_uploaded_file($_FILES['file']['tmp_name']) ) {
    $move_re = move_uploaded_file($_FILES['file']['tmp_name'], $file_path);

    if (!$move_re) {
        echo '上传失败'.PHP_EOL;
    }
}else{
    echo '请检查数据来源'.PHP_EOL;
}

2、对压缩包进行解压

$destination = '/home/wwwroot/labor_con2.zip';

$zip = new ZipArchive;
if ($zip->open($destination, ZIPARCHIVE::CREATE) !== true) {
    echo '服务器错误'.PHP_EOL;
}

//解压到目标目录 $extractDir
$extractDir = '/home/wwwroot/zip';
if (!is_dir($extractDir)) {
    mkdir($extractDir, 0777, true);
}

$zip->extractTo($extractDir);
$zip->close();

3、把解压的文件移动到目标的资源文件夹里

$zipName = 'labor_con2';
$realExtractDir = $extractDir.'/'.$zipName.'/';
$folders = scandir($realExtractDir);

//把$extractToPath 移动到 $targetSrc位置
$targetDir = '/server_images/data/target/';
if (!is_dir($targetDir)) {
    mkdir($targetDir, 0777, true);
}

foreach ( $folders as $file){
    if(!in_array($file,['.','..','.DS_Store'])){

        $sourceSrc = $realExtractDir.$file;
        $targetSrc = $targetDir.$file;

        if (file_exists($sourceSrc)) chmod($sourceSrc, 0755);
        if (file_exists($targetSrc)) chmod($targetSrc, 0755);

        $result = copy($sourceSrc, $targetSrc);
        if($result){
            echo '文件复制成功了'.PHP_EOL;
        }
    }
}

乱码需要用iconv函数转换一下$item['audit_company_id']是数据库里的字段值付给新的变量,打包出来的新文件就不会乱码了。

$dest_root = config_item('image_root_path');
if (!empty($fileLists)) {
    foreach ($fileLists as $item) {
        $handicappedInfo = $this->audit_companys_handicapped_model->get_one_info(['handicapped_id' => $item['handicapped_id'], 'status' => 1, 'audit_company_id' => $item['audit_company_id']], 'username');
        if (!empty($handicappedInfo)) {
            $root = iconv('utf-8', 'gbk', $handicappedInfo['username']);
            $zip->addEmptyDir($root);
            if (!empty($item['path'])) {// 读取文件内容
                $handicapped = iconv('utf-8', 'gbk', $item['name']);
                $zip->addFile($dest_root . $item['path'], $root . '/' . $handicapped . '.' . pathinfo($item['path'],
                        PATHINFO_EXTENSION));
            }
        } else {
            $root = iconv('utf-8', 'gbk', $auditCompanysInfo['company_name']);
            $zip->addEmptyDir($root);
            if (!empty($item['path'])) {
                $name = iconv('utf-8', 'gbk',  $item['name']);
                $zip->addFile($dest_root . $item['path'], $root . '/' . $name . '.' . pathinfo($item['path'],
                        PATHINFO_EXTENSION));
            }
        }
    }
}

4、乱码(高版本)其他方法

private function _detect_encoding($file) {
    $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1');
    $str = file_get_contents($file);
    foreach ($list as $item) {
        $tmp = mb_convert_encoding($str, $item, $item);
        if (md5($tmp) == md5($str)) {
            return $item;
        }
    }
    return null;
}

function auto_read($file, $charset='UTF-8') {
    $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1');
    $str = file_get_contents($file);
    foreach ($list as $item) {
        $tmp = mb_convert_encoding($str, $item, $item);
        if (md5($tmp) == md5($str)) {
            return mb_convert_encoding($str, $charset, $item);
        }
    }
    return "";
}

最后

因为时间关系,等之后抽时间在更新,编码不易,全靠硬挤,加油吧。

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索