一个在线更新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请求一次自动更新,这样安装包的管理能力更强。
方法三:
<?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); } } } }