set_charset('utf8mb4'); // === 파라미터 받기 === $product_code = $_POST['product_code'] ?? ''; $sw_version = $_POST['sw_version'] ?? ''; $version_type = $_POST['version_type'] ?? 'patch'; // major/minor/patch $uploader = $_POST['uploader'] ?? '알 수 없음'; $files = isset($_POST['files']) ? json_decode($_POST['files'], true) : []; if (!$product_code || !$sw_version || empty($files)) { throw new Exception("필수값 누락 (제품코드, 버전, 파일 정보 중 하나가 없습니다)"); } // ✅ 트랜잭션 시작 (중간에 에러나면 데이터베이스를 롤백해서 데이터가 꼬이지 않게 보호함) $conn->begin_transaction(); $inserted = []; foreach ($files as $f) { $filename = $f['name'] ?? ''; $original_name = $f['original'] ?? $filename; $filepath = $f['path'] ?? ''; $filetype = $f['type'] ?? ''; $filesize = $f['size'] ?? 0; $sql = " INSERT INTO deploy_files (product_code, sw_version, version_type, filename, original_name, filepath, filetype, filesize, uploader, upload_date, deleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), 0) ON DUPLICATE KEY UPDATE filename = VALUES(filename), original_name = VALUES(original_name), filepath = VALUES(filepath), filesize = VALUES(filesize), uploader = VALUES(uploader), upload_date = NOW(), deleted = 0 "; $stmt = $conn->prepare($sql); // ✅ 용량이 매우 큰 파일(2GB 이상)의 경우 정수형(i) 바인딩 시 에러가 날 수 있어, 모두 문자열(s)로 바인딩하여 안전하게 MySQL에 넘깁니다. $stmt->bind_param( "sssssssss", $product_code, $sw_version, $version_type, $filename, $original_name, $filepath, $filetype, $filesize, $uploader ); $stmt->execute(); $inserted[] = [ 'filename' => $filename, 'original' => $original_name, 'filetype' => $filetype, 'version' => $sw_version, 'size' => round($filesize/1024/1024, 2)."MB" ]; $stmt->close(); } /* ✅ 버전 기록: deploy_versions_test 업데이트 */ $check = $conn->prepare("SELECT COUNT(*) FROM deploy_versions_test WHERE product_code=?"); $check->bind_param("s", $product_code); $check->execute(); $check->bind_result($cnt); $check->fetch(); $check->close(); if ($cnt > 0) { // 기존 레코드 갱신 $upd = $conn->prepare(" UPDATE deploy_versions_test SET family_version=?, updated_at=NOW() WHERE product_code=? "); $upd->bind_param("ss", $sw_version, $product_code); $upd->execute(); $upd->close(); } else { // 신규 추가 $ins = $conn->prepare(" INSERT INTO deploy_versions_test (product_code, family_version, updated_at) VALUES (?, ?, NOW()) "); $ins->bind_param("ss", $product_code, $sw_version); $ins->execute(); $ins->close(); } // ✅ 위 모든 쿼리가 단 하나의 에러 없이 정상 실행되었을 때만 커밋(진짜 저장) $conn->commit(); // 프론트엔드로 성공 메시지 전달 echo json_encode([ 'success' => true, 'message' => '업로드 DB 기록 완료', 'group' => [ 'files' => $inserted, 'upload' => date('Y-m-d H:i:s'), 'uploader' => $uploader, 'testdone' => '', 'tester' => '', 'release' => '', 'releaser' => '' ] ]); } catch (Exception $e) { // ✅ 쿼리 중 하나라도 에러가 나면 여기로 빠져나와서 롤백 처리 if (isset($conn) && $conn->ping()) { $conn->rollback(); } // 이 메시지가 프론트엔드의 alert 창에 그대로 뜨게 됩니다! echo json_encode([ 'success' => false, 'message' => 'DB 에러 상세 원인: ' . $e->getMessage() ]); } finally { if (isset($conn) && $conn->ping()) { $conn->close(); } } ?>