一个在线更新web、h5的php文件,简单易用,和常用的ftp、git有些区别,本方法对于安装包管理较好

一个在线更新web、h5的包,简单易用的方法是使用FTP工具或者Git进行版本控制和更新。

方法一:使用FTP工具 1. 使用FTP客户端(如FileZilla)连接到服务器。 2. 浏览到需要更新的文件所在的目录。 3. 将本地文件上传到服务器上对应的目录。 4. 删除服务器上的旧文件。 5. 将新文件从本地复制到服务器上对应的目录。

方法二:使用Git 1. 在本地创建一个Git仓库,并将需要更新的文件添加到仓库中。 2. 在服务器上安装Git并配置好远程仓库地址。 3. 将本地仓库推送到远程仓库。 4. 在服务器上拉取远程仓库的最新代码。 5. 将新文件部署到服务器上对应的目录。

这两种方法都可以实现在线更新web、h5安装包,下面写了一个用php实现这种功能,用于在后台直接上传zip包后curd请求一次自动更新,这样安装包的管理能力更强。image.png


方法三:

<?php

define('APP_UPDATE_DEBUG', true);//是否调试
if (APP_UPDATE_DEBUG) {
    error_reporting(E_ALL);//显示所有错误
    ini_set('display_errors', 'on');
} else {
    error_reporting(0);//关闭所有错误
    ini_set('display_errors', 'off');
}

(new AppUpdate)->run();//执行

class AppUpdate
{
    const APP_UPDATE_API = 'https://abc.com/app_version';//更新接口
    const APP_UPDATE_TYPE = 'h5';//更新平台
    const APP_UPDATE_SECRET = 'jx5HTGJiNq8U2BmzYwKbRoLtyd6Drp7C';//密钥
    const APP_UPDATE_TOKEN_TYPE = 'md5';//token验证方式
    const APP_UPDATE_DELETE_DIR = ['/static/', '/uni_modules/'];//删除目录
    const APP_UPDATE_NEED_BACKUP = false;//是否备份
    const APP_UPDATE_BACKUP_DIR = '/backup/';//备份目录
    const APP_UPDATE_UNNEED_FILE = ['.', '..', '.user.ini', '.idea', '.well-known', '.htaccess', '.nginx.htaccess', 'version'];//不用压缩的文件

    //验证token
    private static function check_token()
    {
        $token = !empty($_REQUEST['token']) ? $_REQUEST['token'] : '';
        if (!$token) {
            self::run_exit('token is empty');
        }
        //自定义验证token
        $method = self::APP_UPDATE_TOKEN_TYPE;
        if ($token != $method(self::APP_UPDATE_SECRET)) {
            self::run_exit('token is error');
        }
    }

    //执行
    public function run()
    {
        self::check_token();
        $version = (int)@file_get_contents(__DIR__ . '/version');
        $version = $version > 0 ? $version : 100;
        //更新检测接口
        $url = self::APP_UPDATE_API . '?type=' . self::APP_UPDATE_TYPE . '&version=' . $version;
        $res = $this->get($url);
        if (empty($res) || $res['status'] == 200) {
            self::run_exit('没有更新');
        }
        $info = $res['data'];
        if ($info['version'] <= $version || empty($info['url'])) {
            self::run_exit('无须更新');
        }
        //下载更新包
        $fileName = __DIR__ . '/new' . $info['version'] . '.zip';
        $file = $this->remote2local($info['url'], $fileName);
        if (!file_exists($fileName)) {
            self::run_exit('下载失败');
        }
        //执行备份
        if (self::APP_UPDATE_NEED_BACKUP) {
            $this->backup();
        }

        // 要删除目录
        if (!empty(self::APP_UPDATE_DELETE_DIR)) {
            foreach (self::APP_UPDATE_DELETE_DIR as $dir) {
                $this->deleteDirectory(__DIR__ . $dir);
            }
        }

        $zip = new \ZipArchive ();
        $zip->open($fileName);
        $decode = $zip->extractTo(__DIR__ . '/');
        $zip->close();
        if (!$decode) {
            self::run_exit('解压失败');
        }
        //更新版本号
        @file_put_contents(__DIR__ . '/version', $info['version']);
        @unlink($fileName);//删除压缩包
        self::run_exit('升级成功');
    }


    //输出
    private static function run_exit($msg)
    {
        exit($msg);
    }

    //获取远程文件
    private function get($url)
    {
        $headerArray = ["Content-type:application/json;", "Accept:application/json"];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        if (APP_UPDATE_DEBUG) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);
        $output = curl_exec($ch);

        if (curl_errno($ch)) {
            self:: run_exit(curl_error($ch));
        }
        curl_close($ch);
        if (stripos($output, '{') === 0) {
            return json_decode($output, true);
        }
        return $output;
    }

    //删除目录
    private function deleteDirectory($directoryPath)
    {
        if (!is_dir($directoryPath)) {
            return;
        }
        $iterator = new \RecursiveDirectoryIterator($directoryPath, \RecursiveDirectoryIterator::SKIP_DOTS);
        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($iterator as $file) {
            $file->isFile() ? unlink($file->getRealPath()) : rmdir($file->getRealPath());
        }
        rmdir($directoryPath);
    }

    //备份旧文件
    private function backup()
    {
        $dir = __DIR__ . self::APP_UPDATE_BACKUP_DIR;
        if (!is_dir($dir)) {
            @mkdir($dir, 0777, true);
        }
        if (!is_writeable($dir)) {
            self::run_exit('备份目录没有写入权限');
        }
        $zipName = $dir . date('YmdHi') . '.zip';
        $zip = new \ZipArchive ();
        $zip->open($zipName, \ZipArchive::CREATE);
        $this->createZip(opendir($dir), $zip, $dir);
        $zip->close();
        if (!file_exists($zipName)) {
            self::run_exit('备份失败');
        }
    }

    //远程文件转本地文件
    private function remote2local($url, $localPath)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //开发环境取消ssl认证
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        $res = curl_exec($ch);
        if (curl_errno($ch)) {
            return false;
        }
        curl_close($ch);
        //保存到本地
        $file = fopen($localPath, 'w');
        fwrite($file, $res);
        fclose($file);
        return $localPath;
    }


    //递归创建压缩包
    private function createZip($openFile, $zipObj, $sourcePath, $newRelat = '')
    {
        while (($file = readdir($openFile)) != false) {
            if (in_array($file, self::APP_UPDATE_UNNEED_FILE)) {
                continue;
            }
            //跳过压缩包,主要是备份的文件
            if (substr($file, -4) == '.zip') continue;
            /*源目录路径(绝对路径)*/
            $sourceTemp = $sourcePath . '/' . $file;
            /*目标目录路径(相对路径)*/
            $newTemp = $newRelat == '' ? $file : $newRelat . '/' . $file;
            if (is_dir($sourceTemp)) {
                $zipObj->addEmptyDir($newTemp);
                $this->createZip(opendir($sourceTemp), $zipObj, $sourceTemp, $newTemp);
            }
            if (is_file($sourceTemp)) {
                $zipObj->addFile($sourceTemp, $newTemp);
            }
        }
    }
}


评论/留言