TA的每日心情 | 奋斗 3 天前 |
|---|
签到天数: 5 天 连续签到: 1 天 [LV.2]偶尔看看I 766680204
|

|
/**
* 完整的ZIP文件处理解决方案(兼容PHP 8.3)
* 功能:下载ZIP文件、验证MD5、解压加密ZIP
*/
- class ZipProcessor {
- private $tempDir;
- public function __construct() {
- $this->tempDir = sys_get_temp_dir();
- $this->checkDependencies();
- }
- private function checkDependencies() {
- if (!extension_loaded('curl')) {
- throw new Exception("需要CURL扩展支持");
- }
- if (!extension_loaded('zip')) {
- throw new Exception("需要ZIP扩展支持");
- }
- }
- public function processApiResponse($apiResponse, $extractDir) {
- try {
-
- $responseData = $this->parseApiResponse($apiResponse);
-
- $zipFile = $this->downloadZipFile($responseData['download_url']);
-
- $this->verifyFileIntegrity($zipFile, $responseData['zip_md5'], $responseData['zip_size']);
-
- $this->extractZipFile($zipFile, $extractDir, $responseData['zip_password']);
-
- $this->cleanupTempFiles($zipFile);
- return [
- 'success' => true,
- 'message' => 'ZIP文件处理成功',
- 'version' => $responseData['version'],
- 'extract_dir' => realpath($extractDir)
- ];
- } catch (Exception $e) {
- if (isset($zipFile) && file_exists($zipFile)) {
- $this->cleanupTempFiles($zipFile);
- }
- return [
- 'success' => false,
- 'message' => $e->getMessage()
- ];
- }
- }
- /**
- * 解析API响应
- */
- private function parseApiResponse($apiResponse) {
- $responseData = json_decode($apiResponse, true);
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new Exception("JSON解析失败: " . json_last_error_msg());
- }
- if (!isset($responseData['code']) || $responseData['code'] !== 0) {
- throw new Exception("API错误: " . ($responseData['msg'] ?? '未知错误'));
- }
- if (!isset($responseData['data'])) {
- throw new Exception("API响应格式错误: 缺少data字段");
- }
- $requiredFields = ['download_url', 'zip_password', 'zip_md5', 'version'];
- foreach ($requiredFields as $field) {
- if (!isset($responseData['data'][$field])) {
- throw new Exception("API响应格式错误: 缺少data字段 $field");
- }
- }
- return $responseData['data'];
- }
- /**
- * 下载ZIP文件
- */
- private function downloadZipFile($url) {
- $tempFile = tempnam($this->tempDir, 'zip_download_');
- $ch = curl_init($url);
- $fp = fopen($tempFile, 'w');
- if (!$fp) {
- throw new Exception("无法创建临时文件: $tempFile");
- }
- curl_setopt_array($ch, [
- CURLOPT_FILE => $fp,
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_AUTOREFERER => true,
- CURLOPT_MAXREDIRS => 5,
- CURLOPT_TIMEOUT => 60,
- CURLOPT_CONNECTTIMEOUT => 30,
- CURLOPT_SSL_VERIFYPEER => false,
- CURLOPT_SSL_VERIFYHOST => false,
- CURLOPT_USERAGENT => 'PHP-ZipProcessor/1.0'
- ]);
- $result = curl_exec($ch);
- if ($result === false) {
- $error = curl_error($ch);
- fclose($fp);
- unlink($tempFile);
- curl_close($ch);
- throw new Exception("下载失败: $error");
- }
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
- curl_close($ch);
- fclose($fp);
- if ($httpCode < 200 || $httpCode >= 300) {
- unlink($tempFile);
- throw new Exception("HTTP错误: $httpCode");
- }
- if (!in_array($contentType, ['application/zip', 'application/x-zip-compressed', 'application/octet-stream'])) {
- unlink($tempFile);
- throw new Exception("下载的文件不是ZIP格式: $contentType");
- }
- if (filesize($tempFile) === 0) {
- unlink($tempFile);
- throw new Exception("下载的文件为空");
- }
- return $tempFile;
- }
- /**
- * 验证文件完整性
- */
- private function verifyFileIntegrity($filePath, $expectedMd5, $expectedSize = null) {
- // 验证MD5
- $actualMd5 = md5_file($filePath);
- if (strtolower($actualMd5) !== strtolower($expectedMd5)) {
- throw new Exception("MD5验证失败\n实际: $actualMd5\n期望: $expectedMd5");
- }
- // 验证文件大小(如果提供)
- if ($expectedSize !== null && $expectedSize !== '0') {
- $actualSize = filesize($filePath);
- $expectedBytes = $this->humanToBytes($expectedSize);
- if ($expectedBytes > 0 && abs($actualSize - $expectedBytes) > 1024) { // 允许1KB误差
- throw new Exception("文件大小不匹配\n实际: " . $this->bytesToHuman($actualSize) .
- "\n期望: $expectedSize");
- }
- }
- }
- /**
- * 解压ZIP文件(兼容PHP 8.3)
- */
- private function extractZipFile($zipFile, $extractDir, $password) {
- // 创建解压目录
- if (!file_exists($extractDir)) {
- if (!mkdir($extractDir, 0755, true)) {
- throw new Exception("无法创建解压目录: $extractDir");
- }
- }
- if (!is_writable($extractDir)) {
- throw new Exception("解压目录不可写: $extractDir");
- }
- $zip = new ZipArchive();
- $openResult = $zip->open($zipFile);
- if ($openResult !== true) {
- throw new Exception("无法打开ZIP文件: " . $this->getZipErrorText($openResult));
- }
- try {
- // 尝试使用密码(兼容PHP 8.3)
- $zip->setPassword($password);
- // 检查ZIP文件是否有内容
- if ($zip->numFiles === 0) {
- throw new Exception("ZIP文件为空");
- }
- // 尝试解压所有文件
- $success = false;
- // 先尝试解压第一个文件测试密码
- $firstFileName = $zip->getNameIndex(0);
- if ($zip->extractTo($extractDir, $firstFileName)) {
- // 密码正确,继续解压其他文件
- for ($i = 1; $i < $zip->numFiles; $i++) {
- $fileName = $zip->getNameIndex($i);
- $zip->extractTo($extractDir, $fileName);
- }
- $success = true;
- } else {
- // 可能是密码错误,尝试不使用密码
- $zip->setPassword('');
- if ($zip->extractTo($extractDir)) {
- $success = true;
- } else {
- // 检查具体错误
- if ($openResult === ZipArchive::ER_WRONGPASSWD) {
- throw new Exception("ZIP文件密码错误");
- }
- throw new Exception("解压失败");
- }
- }
- if (!$success) {
- throw new Exception("解压失败");
- }
- } finally {
- $zip->close();
- }
- return true;
- }
- private function cleanupTempFiles($filePath) {
- if (file_exists($filePath)) {
- unlink($filePath);
- }
- }
- /**
- * 获取ZIP错误信息
- */
- private function getZipErrorText($errorCode) {
- $errors = [
- ZipArchive::ER_EXISTS => '文件已存在',
- ZipArchive::ER_INCONS => 'Zip文件不一致',
- ZipArchive::ER_INVAL => '无效的参数',
- ZipArchive::ER_MEMORY => '内存分配失败',
- ZipArchive::ER_NOENT => '没有这样的文件',
- ZipArchive::ER_NOZIP => '不是zip归档',
- ZipArchive::ER_OPEN => '无法打开文件',
- ZipArchive::ER_READ => '读取错误',
- ZipArchive::ER_SEEK => '查找错误',
- ZipArchive::ER_WRONGPASSWD => '密码错误'
- ];
- return $errors[$errorCode] ?? "未知错误: $errorCode";
- }
- /**
- * 人类可读大小转字节
- */
- private function humanToBytes($size) {
- if ($size === null || $size === '') return 0;
- $units = ['B', 'KB', 'MB', 'GB', 'TB'];
- $unit = strtoupper(substr($size, -2));
- if (!in_array($unit, $units)) {
- $unit = strtoupper(substr($size, -1));
- }
- $value = (float)trim(rtrim($size, $unit));
- $power = array_search($unit, $units);
- return $value * pow(1024, $power);
- }
- /**
- * 字节转人类可读大小
- */
- private function bytesToHuman($bytes) {
- $units = ['B', 'KB', 'MB', 'GB', 'TB'];
- $power = floor(log($bytes, 1024));
- return round($bytes / pow(1024, $power), 2) . $units[$power];
- }
- }
- // 使用示例
- try {
- // API响应数据
- $apiResponse = '{
- "code": 0,
- "msg": "加密更新包生成成功",
- "data": {
- "download_url": ",
- "zip_password": "e26d556899c456915a61341802dad137",
- "zip_size": "3.56KB",
- "zip_md5": "90e356e66c38a0c5c9d023e94aa750e1",
- "version": "3.1.20250928",
- "cxid": 2
- }
- }';
- $extractDirectory = ROOT;
- $processor = new ZipProcessor();
- // 执行处理流程
- $result = $processor->processApiResponse($apiResponse, $extractDirectory);
- if ($result['success']) {
- echo "✅ 处理成功!\n";
- echo "📁 解压目录: " . $result['extract_dir'] . "\n";
- echo "🔢 版本号: " . $result['version'] . "\n";
- } else {
- echo "❌ 处理失败: " . $result['message'] . "\n";
- }
- } catch (Exception $e) {
- echo "⚠️ 系统错误: " . $e->getMessage() . "\n";
- }
复制代码
|
|