lh 1 month ago
parent
commit
3b9285a6cc
1 changed files with 74 additions and 38 deletions
  1. 74 38
      app/Http/Controllers/Anime/AnimeController.php

+ 74 - 38
app/Http/Controllers/Anime/AnimeController.php

@@ -1471,8 +1471,13 @@ class AnimeController extends BaseController
                 mkdir($tempDir, 0755, true);
             }
             
-            // 下载文件
+            // 并行下载文件(使用 cURL multi)
             $downloadedFiles = [];
+            $multiHandle = curl_multi_init();
+            $curlHandles = [];
+            $fileInfos = [];
+            
+            // 准备所有下载任务
             foreach ($segments as $index => $segment) {
                 try {
                     if ($isAceMode) {
@@ -1504,59 +1509,86 @@ class AnimeController extends BaseController
                     }
                     $filePath = $tempDir . '/' . $fileName;
                     
-                    // 下载文件
-                    $context = stream_context_create([
-                        'http' => [
-                            'timeout' => 30,
-                            'follow_location' => 1,
-                            'ignore_errors' => true
-                        ],
-                        'ssl' => [
-                            'verify_peer' => false,
-                            'verify_peer_name' => false
-                        ]
-                    ]);
+                    // 创建 cURL 句柄
+                    $ch = curl_init($mediaUrl);
+                    $fp = fopen($filePath, 'wb');
+                    
+                    curl_setopt($ch, CURLOPT_FILE, $fp);
+                    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+                    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
+                    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
                     
-                    $fileData = @file_get_contents($mediaUrl, false, $context);
+                    curl_multi_add_handle($multiHandle, $ch);
                     
-                    if ($fileData !== false && !empty($fileData)) {
-                        file_put_contents($filePath, $fileData);
-                        $downloadedFiles[] = $filePath;
+                    $curlHandles[(int)$ch] = [
+                        'handle' => $ch,
+                        'file' => $fp,
+                        'path' => $filePath,
+                        'url' => $mediaUrl,
+                        'segment' => $segment
+                    ];
+                    
+                } catch (\Exception $e) {
+                    $logData = ['error' => $e->getMessage()];
+                    if ($isAceMode) {
+                        $logData['act_id'] = $segment->act_id;
                     } else {
-                        $logData = [
-                            'media_url' => $mediaUrl,
-                            'type' => $isAceMode ? 'video' : (!empty($segment->video_url) ? 'video' : 'image')
-                        ];
-                        
-                        if ($isAceMode) {
-                            $logData['act_id'] = $segment->act_id;
-                            $logData['act_number'] = $segment->act_number;
-                        } else {
-                            $logData['segment_id'] = $segment->segment_id;
-                            $logData['segment_number'] = $segment->segment_number;
-                        }
-                        
-                        logDB('anime', 'warning', '文件下载失败', $logData);
+                        $logData['segment_id'] = $segment->segment_id;
+                    }
+                    logDB('anime', 'error', '准备下载任务异常', $logData);
+                    continue;
+                }
+            }
+            
+            // 执行并行下载
+            $running = null;
+            do {
+                curl_multi_exec($multiHandle, $running);
+                curl_multi_select($multiHandle, 0.1);
+            } while ($running > 0);
+            
+            // 处理下载结果
+            foreach ($curlHandles as $info) {
+                $ch = $info['handle'];
+                $fp = $info['file'];
+                $filePath = $info['path'];
+                $segment = $info['segment'];
+                
+                fclose($fp);
+                
+                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+                
+                if ($httpCode == 200 && file_exists($filePath) && filesize($filePath) > 0) {
+                    $downloadedFiles[] = $filePath;
+                } else {
+                    // 删除失败的文件
+                    if (file_exists($filePath)) {
+                        @unlink($filePath);
                     }
                     
-                } catch (\Exception $e) {
                     $logData = [
-                        'error' => $e->getMessage()
+                        'media_url' => $info['url'],
+                        'http_code' => $httpCode,
+                        'type' => $isAceMode ? 'video' : 'image'
                     ];
                     
                     if ($isAceMode) {
                         $logData['act_id'] = $segment->act_id;
-                        $logData['act_number'] = $segment->act_number;
                     } else {
                         $logData['segment_id'] = $segment->segment_id;
-                        $logData['segment_number'] = $segment->segment_number;
                     }
                     
-                    logDB('anime', 'error', '下载文件异常', $logData);
-                    continue;
+                    logDB('anime', 'warning', '文件下载失败', $logData);
                 }
+                
+                curl_multi_remove_handle($multiHandle, $ch);
+                curl_close($ch);
             }
             
+            curl_multi_close($multiHandle);
+            
             if (empty($downloadedFiles)) {
                 // 清理临时目录
                 if (file_exists($tempDir)) {
@@ -1714,7 +1746,11 @@ class AnimeController extends BaseController
                 Utils::throwError('20003:创建ZIP文件失败');
             }
             
-            // 添加文件到zip(使用完整路径确保文件正确添加)
+            // 设置压缩级别为最快(0=不压缩,1=最快,9=最好压缩)
+            // 对于视频和图片,压缩效果不明显,使用最快速度
+            $zip->setCompressionIndex(0, \ZipArchive::CM_STORE); // 不压缩,直接存储
+            
+            // 添加文件到zip
             foreach ($downloadedFiles as $file) {
                 if (file_exists($file)) {
                     $zip->addFile($file, basename($file));