connect_error) { die("연결 실패: " . $conn->connect_error); } /** * 3. DB 조회 (중요 수정 사항) * 동일한 filepath가 여러 개일 경우: * 1순위: release_date가 있는 것 우선 (DESC) * 2순위: 가장 최근에 업로드된 것 우선 (upload_date DESC) */ $sql = "SELECT release_date FROM deploy_files WHERE filepath = ? ORDER BY (release_date IS NULL), release_date DESC, upload_date DESC LIMIT 1"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $filepath); $stmt->execute(); $stmt->bind_result($release_date); $fetch_success = $stmt->fetch(); $stmt->close(); $conn->close(); // DB에 해당 파일 경로 자체가 없는 경우 if (!$fetch_success) { exit("DB에서 파일 정보를 찾을 수 없습니다. 경로: " . htmlspecialchars($filepath)); } /** * 4. 버킷 결정 로직 * 데이터가 존재하고, NULL/공백/0000-00-00이 아닐 때만 release 버킷 사용 */ $is_released = (!empty($release_date) && $release_date !== '0000-00-00'); $bucket = $is_released ? 'baron-software-release' : 'baron-software-test'; // 5. S3 Client 설정 $s3 = new S3Client([ 'version' => 'latest', 'region' => 'auto', 'endpoint'=> 'https://81fa2d48964d31dd0da9558f9ce601d1.r2.cloudflarestorage.com', 'credentials' => [ 'key' => '11d7027f505658acb3aeb40c3955a206', 'secret' => '65a78f6c582e0bdfccc2f431fc7b7be2ba11f999f0a8a87142011eac8b84761f', ], 'use_path_style_endpoint' => true ]); try { // 6. Presigned URL 생성 (10분 유효) $cmd = $s3->getCommand('GetObject', [ 'Bucket' => $bucket, 'Key' => $filepath, 'ResponseContentDisposition' => 'attachment; filename="' . rawurlencode($filename) . '"' ]); $request = $s3->createPresignedRequest($cmd, '+10 minutes'); // 7. R2 직접 다운로드 주소로 리다이렉트 header("Location: " . (string)$request->getUri()); exit; } catch (Exception $e) { exit("다운로드 링크 생성 실패: " . $e->getMessage()); } ?>