rkljw hai 1 día
pai
achega
f2bc3fceb2
Modificáronse 1 ficheiros con 245 adicións e 215 borrados
  1. 245 215
      app/Controller/PublicController.php

+ 245 - 215
app/Controller/PublicController.php

@@ -10,7 +10,6 @@ use App\Tools\CommonService;
 use App\Tools\PublicData;
 use App\Tools\Result;
 use function Hyperf\Support\env;
-use function Hyperf\Coroutine\parallel;
 use Hyperf\Context\Context;
 use Hyperf\Di\Annotation\Inject;
 use Hyperf\HttpServer\Contract\RequestInterface;
@@ -352,8 +351,8 @@ class PublicController extends AbstractController
         // 放开执行时限,避免大量文件导致的超时
         ignore_user_abort(true);
         @set_time_limit(0);
-
-        // 验证参数
+        
+        //验证是否有传参数
         $requireData = $this->request->all();
         $validator = $this->validationFactory->make(
             $requireData,
@@ -368,156 +367,252 @@ class PublicController extends AbstractController
             $errorMessage = $validator->errors()->first();
             return Result::error($errorMessage);
         }
-
         $requireData['fileName'] = $requireData['fileName'] ?? '政讯通';
-
-        // 归一化文件与名称
-        /** @var array<int|string, string> $files */
-        $files = [];
-        if (is_array($requireData['files'])) {
-            // 保留原有索引,避免与 names 对应关系错位
-            $files = array_filter($requireData['files'], fn($v) => is_string($v) && $v !== '');
-        } elseif (is_string($requireData['files'])) {
-            $files = [$requireData['files']];
-        }
-        $names = [];
-        if (isset($requireData['names']) && is_array($requireData['names'])) {
-            $names = $requireData['names'];
-        }
-
-        if (count($files) === 0) {
-            return Result::error('文件不能为空');
-        }
-
-        // 预下载远程文件(并发)
-        $remoteIndexes = [];
-        foreach ($files as $index => $path) {
-            if (is_string($path) && filter_var($path, FILTER_VALIDATE_URL)) {
-                $remoteIndexes[] = $index;
-            }
-        }
-
-        $tempFiles = [];
-        if (!empty($remoteIndexes)) {
-            $concurrency = (int) env('ZIP_DOWNLOAD_CONCURRENCY', 5);
-            $tasks = [];
-            foreach ($remoteIndexes as $idx) {
-                $url = $files[$idx];
-                $tasks[] = function () use ($idx, $url) {
-                    $temp = $this->downloadRemoteToTemp($url);
-                    return [$idx, $temp];
-                };
-            }
-            try {
-                $results = parallel($concurrency, $tasks);
-                foreach ($results as $result) {
-                    if (is_array($result) && count($result) === 2) {
-                        [$i, $temp] = $result;
-                        if (is_string($temp) && $temp !== '' && is_file($temp)) {
-                            $tempFiles[$i] = $temp;
-                        }
-                    }
-                }
-            } catch (\Throwable $e) {
-                // 并发下载异常不终止,尽量继续处理其他文件
-            }
-        }
-
-        // 创建 ZIP 目录与文件
+        //打包文件
         $zip = new ZipArchive();
         $fileType = 'zip';
         $date = date('Ymd');
         $filePath = $fileType . DIRECTORY_SEPARATOR . $date;
-        $allDir = 'public' . DIRECTORY_SEPARATOR . $filePath;
-        if (!is_dir($allDir) && !mkdir($allDir, 0755, true) && !is_dir($allDir)) {
-            // 清理已下载的临时文件
-            foreach ($tempFiles as $temp) {
-                @unlink($temp);
+        // 使用绝对路径并规范化
+        $allDir = BASE_PATH . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . $filePath;
+        $allDir = realpath($allDir) ?: $allDir;
+        
+        // 打印目录路径以便调试
+        error_log("DownloadFile: Full directory path: $allDir");
+        
+        if (!is_dir($allDir)) {
+            if (!mkdir($allDir, 0755, true)) {
+                error_log("DownloadFile: Failed to create directory: $allDir");
+                return Result::error('创建文件夹失败');
             }
-            return Result::error('创建文件夹失败');
         }
-
+        // 生成绝对路径的ZIP文件名
         $zipFileName = $allDir . DIRECTORY_SEPARATOR . $requireData['fileName'] . time() . mt_rand(1, 1000000) . '.zip';
-
-        $addedAny = false;
-        $zipOpened = false;
-        try {
-            if ($zip->open($zipFileName, ZipArchive::CREATE) !== true) {
-                return Result::error('无法创建zip文件');
+        error_log("DownloadFile: ZIP file path: $zipFileName");
+        error_log("DownloadFile: Directory exists: " . (is_dir($allDir) ? 'yes' : 'no'));
+        error_log("DownloadFile: Directory writable: " . (is_writable($allDir) ? 'yes' : 'no'));
+
+        // 添加OVERWRITE标志确保文件可以被创建
+        if ($zip->open($zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
+            // 将要下载的文件逐个添加到zip文件中
+            /** @var array<string> $files */
+            $files = [];
+            if (is_array($requireData['files'])) {
+                $files = $requireData['files'];
+            } elseif (is_string($requireData['files'])) {
+                $files = [$requireData['files']];
             }
-            $zipOpened = true;
-
-            foreach ($files as $index => $originalPath) {
-                if (!is_string($originalPath) || $originalPath === '') {
+            
+            // 添加进度日志
+            error_log("DownloadFile: Processing " . count($files) . " files");
+            
+            $addedCount = 0;
+            $failedCount = 0;
+            
+            foreach ($files as $key => $filePathu) {
+                if (!is_string($filePathu)) {
                     continue;
                 }
-
-                // 决定压缩包内的文件名
-                $zipInnerName = $names[$index] ?? '';
-                if (!is_string($zipInnerName) || $zipInnerName === '') {
-                    if (filter_var($originalPath, FILTER_VALIDATE_URL)) {
-                        $zipInnerName = basename(parse_url($originalPath, PHP_URL_PATH) ?: ('file_' . ($index + 1) . $this->getFileExtension($originalPath)));
-                    } else {
-                        $zipInnerName = basename($originalPath);
-                        if ($zipInnerName === '' || $zipInnerName === '.' || $zipInnerName === '..') {
-                            $zipInnerName = 'file_' . ($index + 1) . $this->getFileExtension($originalPath);
+                
+                // 生成文件名:key + 1
+                $innerFileName = $requireData['names'][$key] ?? 'file_' . ($key + 1); //($key + 1) . $this->getFileExtension($filePathu);
+                
+                // 处理远程URL文件
+                if (filter_var($filePathu, FILTER_VALIDATE_URL)) {
+                    error_log("DownloadFile: Processing remote file $key: $filePathu");
+                    $this->addRemoteFileToZip($zip, $filePathu, $innerFileName);
+                    $addedCount++;
+                } else {
+                    // 处理本地文件
+                    error_log("DownloadFile: Processing local file $key: $filePathu");
+                    if (!file_exists($filePathu)) {
+                        // 尝试添加public前缀
+                        $fullPath = 'public/' . $filePathu;
+                        if (!file_exists($fullPath)) {
+                            var_dump("local路径:",BASE_PATH);
+                            // 尝试使用绝对路径
+                            $fullPath = BASE_PATH . '/public/' . $filePathu;
+                            if (!file_exists($fullPath)) {
+                                error_log("DownloadFile: File not found: $filePathu");
+                                $failedCount++;
+                                continue; // 跳过不存在的文件
+                            }
                         }
+                        $filePathu = $fullPath;
                     }
-                }
-
-                // 远程:使用预下载的临时文件
-                if (array_key_exists($index, $tempFiles)) {
-                    $tempPath = $tempFiles[$index];
-                    if (is_file($tempPath) && is_readable($tempPath)) {
-                        if ($zip->addFile($tempPath, $zipInnerName)) {
-                            $addedAny = true;
+                    
+                    // 确保文件存在且可读
+                    if (is_file($filePathu) && is_readable($filePathu)) {
+                        if ($zip->addFile($filePathu, $innerFileName)) {
+                            $addedCount++;
+                            error_log("DownloadFile: Successfully added local file: $innerFileName");
+                        } else {
+                            $failedCount++;
+                            error_log("DownloadFile: Failed to add local file: $innerFileName");
                         }
+                    } else {
+                        $failedCount++;
+                        error_log("DownloadFile: File not readable: $filePathu");
                     }
+                }
+            }
+            
+            error_log("DownloadFile: Summary - Added: $addedCount, Failed: $failedCount");
+            
+            // 关闭zip文件
+            $closeResult = $zip->close();
+            error_log("DownloadFile: ZIP close result: " . ($closeResult ? 'success' : 'failed'));
+            
+            if (!$closeResult) {
+                error_log("DownloadFile: Failed to close ZIP file: $zipFileName");
+                return Result::error('ZIP文件关闭失败');
+            }
+            
+            // 检查ZIP文件是否创建成功
+            if (!file_exists($zipFileName)) {
+                error_log("DownloadFile: ZIP file does not exist after close: $zipFileName");
+                return Result::error('ZIP文件创建失败');
+            }
+            
+            $zipFileSize = filesize($zipFileName);
+            if ($zipFileSize === false || $zipFileSize === 0) {
+                error_log("DownloadFile: ZIP file is empty or cannot get size: $zipFileName");
+                return Result::error('ZIP文件为空');
+            }
+            
+            error_log("DownloadFile: ZIP file created successfully: $zipFileName (size: $zipFileSize bytes)");
+            
+            // 将zip文件提供给用户进行下载
+            $fileUrlName = explode("public", $zipFileName);
+            if (count($fileUrlName) < 2) {
+                return Result::error('无法生成下载链接');
+            }
+            
+            $downloadUrl = env('HOST') . $fileUrlName[1];
+            error_log("DownloadFile: Download URL: $downloadUrl");
+            
+            return Result::success(['fileUrl' => $downloadUrl]);
+        } else {
+            return Result::error('无法创建zip文件');
+        }"DownloadFile: Full directory path: $allDir");
+        
+        if (!is_dir($allDir)) {
+            if (!mkdir($allDir, 0755, true)) {
+                error_log("DownloadFile: Failed to create directory: $allDir");
+                return Result::error('创建文件夹失败');
+            }
+        }
+        // 生成绝对路径的ZIP文件名
+        $zipFileName = $allDir . DIRECTORY_SEPARATOR . $requireData['fileName'] . time() . mt_rand(1, 1000000) . '.zip';
+//        $zipFileName = 'public/zip/files.zip';
+
+        error_log("DownloadFile: ZIP file path: $zipFileName");
+        error_log("DownloadFile: Directory exists: " . (is_dir($allDir) ? 'yes' : 'no'));
+        error_log("DownloadFile: Directory writable: " . (is_writable($allDir) ? 'yes' : 'no'));
+
+        // 添加OVERWRITE标志确保文件可以被创建
+        if ($zip->open($zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
+            // 将要下载的文件逐个添加到zip文件中
+            /** @var array<string> $files */
+            $files = [];
+            if (is_array($requireData['files'])) {
+                $files = $requireData['files'];
+            } elseif (is_string($requireData['files'])) {
+                $files = [$requireData['files']];
+            }
+            
+            // 添加进度日志
+            error_log("DownloadFile: Processing " . count($files) . " files");
+            
+            $addedCount = 0;
+            $failedCount = 0;
+            
+            foreach ($files as $key => $filePathu) {
+                if (!is_string($filePathu)) {
                     continue;
                 }
-
-                // 本地文件处理
-                $localPath = $originalPath;
-                if (!file_exists($localPath)) {
-                    // 尝试添加 public 前缀
-                    $fullPath = 'public/' . ltrim($localPath, '/');
-                    if (!file_exists($fullPath)) {
-                        // 尝试使用绝对路径
-                        $fullPath = BASE_PATH . '/public/' . ltrim($localPath, '/');
+                
+                // 生成文件名:key + 1
+                $innerFileName = $requireData['names'][$key] ?? 'file_' . ($key + 1); //($key + 1) . $this->getFileExtension($filePathu);
+                
+                // 处理远程URL文件
+                if (filter_var($filePathu, FILTER_VALIDATE_URL)) {
+                    error_log("DownloadFile: Processing remote file $key: $filePathu");
+                    $this->addRemoteFileToZip($zip, $filePathu, $innerFileName);
+                    $addedCount++;
+                } else {
+                    // 处理本地文件
+                    error_log("DownloadFile: Processing local file $key: $filePathu");
+                    if (!file_exists($filePathu)) {
+                        // 尝试添加public前缀
+                        $fullPath = 'public/' . $filePathu;
                         if (!file_exists($fullPath)) {
-                            continue; // 跳过不存在的文件
+                            var_dump("local路径:",BASE_PATH);
+                            // 尝试使用绝对路径
+                            $fullPath = BASE_PATH . '/public/' . $filePathu;
+                            if (!file_exists($fullPath)) {
+                                error_log("DownloadFile: File not found: $filePathu");
+                                $failedCount++;
+                                continue; // 跳过不存在的文件
+                            }
                         }
+                        $filePathu = $fullPath;
                     }
-                    $localPath = $fullPath;
-                }
-
-                if (is_file($localPath) && is_readable($localPath)) {
-                    if ($zip->addFile($localPath, $zipInnerName)) {
-                        $addedAny = true;
+                    
+                    // 确保文件存在且可读
+                    if (is_file($filePathu) && is_readable($filePathu)) {
+                        if ($zip->addFile($filePathu, $innerFileName)) {
+                            $addedCount++;
+                            error_log("DownloadFile: Successfully added local file: $innerFileName");
+                        } else {
+                            $failedCount++;
+                            error_log("DownloadFile: Failed to add local file: $innerFileName");
+                        }
+                    } else {
+                        $failedCount++;
+                        error_log("DownloadFile: File not readable: $filePathu");
                     }
                 }
             }
-        } finally {
-            // 关闭 zip
-            if ($zipOpened) {
-                $zip->close();
-            } elseif (file_exists($zipFileName) && filesize($zipFileName) === 0) {
-                // 若未成功打开或写入,确保不会遗留空文件
-                @unlink($zipFileName);
+            
+            error_log("DownloadFile: Summary - Added: $addedCount, Failed: $failedCount");
+            
+            // 关闭zip文件
+            $closeResult = $zip->close();
+            error_log("DownloadFile: ZIP close result: " . ($closeResult ? 'success' : 'failed'));
+            
+            if (!$closeResult) {
+                error_log("DownloadFile: Failed to close ZIP file: $zipFileName");
+                return Result::error('ZIP文件关闭失败');
             }
-            // 清理临时文件
-            foreach ($tempFiles as $temp) {
-                @unlink($temp);
+            
+            // 检查ZIP文件是否创建成功
+            if (!file_exists($zipFileName)) {
+                error_log("DownloadFile: ZIP file does not exist after close: $zipFileName");
+                return Result::error('ZIP文件创建失败');
             }
+            
+            $zipFileSize = filesize($zipFileName);
+            if ($zipFileSize === false || $zipFileSize === 0) {
+                error_log("DownloadFile: ZIP file is empty or cannot get size: $zipFileName");
+                return Result::error('ZIP文件为空');
+            }
+            
+            error_log("DownloadFile: ZIP file created successfully: $zipFileName (size: $zipFileSize bytes)");
+            
+            // 将zip文件提供给用户进行下载
+            $fileUrlName = explode("public", $zipFileName);
+            if (count($fileUrlName) < 2) {
+                return Result::error('无法生成下载链接');
+            }
+            
+            $downloadUrl = env('HOST') . $fileUrlName[1];
+            error_log("DownloadFile: Download URL: $downloadUrl");
+            
+            return Result::success(['fileUrl' => $downloadUrl]);
+        } else {
+            return Result::error('无法创建zip文件');
         }
-
-        if (!$addedAny || !file_exists($zipFileName)) {
-            return Result::error('打包失败或没有可用的文件');
-        }
-
-        // 返回可下载地址
-        $fileUrlName = explode('public', $zipFileName);
-        return Result::success(['fileUrl' => env('HOST') . $fileUrlName[1]]);
     }
     
     /**
@@ -525,9 +620,15 @@ class PublicController extends AbstractController
      */
     private function addRemoteFileToZip($zip, $url, $fileName = null): void
     {
+        var_dump("$$$$$$$$$$$$$$$$$$$$");
+        $tempFile = null;
         try {
             // 创建临时文件
             $tempFile = tempnam(sys_get_temp_dir(), 'remote_file_');
+            if ($tempFile === false) {
+                error_log("DownloadFile: Failed to create temp file for URL: $url");
+                return;
+            }
             
             // 设置更长的超时时间和更好的下载参数
             $context = stream_context_create([
@@ -558,26 +659,26 @@ class PublicController extends AbstractController
             }
             
             if ($fileContent === false) {
-                error_log("Failed to download remote file: " . $url);
+                error_log("DownloadFile: Failed to download remote file: " . $url);
                 return; // 下载失败,跳过
             }
             
             // 验证文件内容
             if (empty($fileContent) || strlen($fileContent) < 100) {
-                error_log("Downloaded file is too small or empty: " . $url);
+                error_log("DownloadFile: Downloaded file is too small or empty: " . $url . " (size: " . strlen($fileContent) . ")");
                 return;
             }
             
             // 写入临时文件并验证
             $bytesWritten = file_put_contents($tempFile, $fileContent);
             if ($bytesWritten === false || $bytesWritten !== strlen($fileContent)) {
-                error_log("Failed to write file content: " . $url);
+                error_log("DownloadFile: Failed to write file content: " . $url . " (written: $bytesWritten, expected: " . strlen($fileContent) . ")");
                 return;
             }
             
             // 验证文件是否可读
             if (!is_readable($tempFile) || filesize($tempFile) < 100) {
-                error_log("Temporary file is not readable or too small: " . $tempFile);
+                error_log("DownloadFile: Temporary file is not readable or too small: " . $tempFile . " (size: " . filesize($tempFile) . ")");
                 return;
             }
             
@@ -591,13 +692,20 @@ class PublicController extends AbstractController
             
             // 添加到zip并验证
             if (!$zip->addFile($tempFile, $fileName)) {
-                error_log("Failed to add file to zip: " . $fileName);
+                error_log("DownloadFile: Failed to add file to zip: " . $fileName);
                 return;
             }
             
+            error_log("DownloadFile: Successfully added remote file to ZIP: $fileName");
+            
         } catch (\Exception $e) {
             // 记录错误但继续处理其他文件
-            error_log("Failed to download remote file: " . $url . " - " . $e->getMessage());
+            error_log("DownloadFile: Exception while downloading remote file: " . $url . " - " . $e->getMessage());
+        } finally {
+            // 清理临时文件
+            if ($tempFile !== null && file_exists($tempFile)) {
+                @unlink($tempFile);
+            }
         }
     }
     
@@ -634,108 +742,30 @@ class PublicController extends AbstractController
         $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
         $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
         $actualLength = strlen($content);
+        $error = curl_error($ch);
         curl_close($ch);
         
         // 检查HTTP状态码和内容长度
         if ($content === false || $httpCode !== 200) {
-            error_log("cURL download failed for URL: $url, HTTP Code: $httpCode");
+            error_log("DownloadFile: cURL download failed for URL: $url, HTTP Code: $httpCode, Error: $error");
             return false;
         }
         
         // 检查内容长度是否匹配
         if ($contentLength > 0 && $actualLength !== $contentLength) {
-            error_log("Content length mismatch for URL: $url, Expected: $contentLength, Actual: $actualLength");
+            error_log("DownloadFile: Content length mismatch for URL: $url, Expected: $contentLength, Actual: $actualLength");
             return false;
         }
         
         // 检查文件是否为空或太小
         if (empty($content) || $actualLength < 100) {
-            error_log("File too small or empty for URL: $url, Size: $actualLength");
+            error_log("DownloadFile: File too small or empty for URL: $url, Size: $actualLength");
             return false;
         }
         
         return $content;
     }
     
-    /**
-     * 下载远程文件到临时文件(流式写入,节省内存),成功返回临时文件路径,失败返回 null
-     */
-    private function downloadRemoteToTemp(string $url, int $timeoutSeconds = 120): ?string
-    {
-        // 优先使用 cURL 流式写入
-        if (function_exists('curl_init')) {
-            $tempFile = tempnam(sys_get_temp_dir(), 'remote_file_');
-            if ($tempFile === false) {
-                return null;
-            }
-            $fp = @fopen($tempFile, 'wb');
-            if ($fp === false) {
-                @unlink($tempFile);
-                return null;
-            }
-            $ch = curl_init();
-            curl_setopt_array($ch, [
-                CURLOPT_URL => $url,
-                CURLOPT_FILE => $fp, // 直接写文件
-                CURLOPT_FOLLOWLOCATION => true,
-                CURLOPT_MAXREDIRS => 5,
-                CURLOPT_CONNECTTIMEOUT => 30,
-                CURLOPT_TIMEOUT => $timeoutSeconds,
-                CURLOPT_SSL_VERIFYPEER => false,
-                CURLOPT_SSL_VERIFYHOST => false,
-                CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
-                CURLOPT_HTTPHEADER => [
-                    'Accept: */*',
-                    'Connection: keep-alive',
-                    'Cache-Control: no-cache',
-                ],
-            ]);
-            $ok = curl_exec($ch);
-            $httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
-            curl_close($ch);
-            fclose($fp);
-
-            if ($ok !== false && $httpCode === 200 && is_file($tempFile) && filesize($tempFile) >= 100) {
-                return $tempFile;
-            }
-            @unlink($tempFile);
-        }
-
-        // 退化为 stream_context + file_get_contents 方案
-        $context = stream_context_create([
-            'http' => [
-                'timeout' => $timeoutSeconds,
-                'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
-                'follow_location' => true,
-                'max_redirects' => 5,
-                'protocol_version' => 1.1,
-                'header' => [
-                    'Accept: */*',
-                    'Connection: keep-alive'
-                ],
-            ],
-            'ssl' => [
-                'verify_peer' => false,
-                'verify_peer_name' => false,
-                'allow_self_signed' => true,
-            ],
-        ]);
-        $content = @file_get_contents($url, false, $context);
-        if ($content === false || strlen((string) $content) < 100) {
-            return null;
-        }
-        $tempFile = tempnam(sys_get_temp_dir(), 'remote_file_');
-        if ($tempFile === false) {
-            return null;
-        }
-        $bytes = @file_put_contents($tempFile, $content);
-        if ($bytes === false || $bytes < 100) {
-            @unlink($tempFile);
-            return null;
-        }
-        return $tempFile;
-    }
-    
     /**
      * 获取文件扩展名
      */