| 594 | } |
| 595 | |
| 596 | void CrossPointWebServer::handleUpload(UploadState& state) const { |
| 597 | static size_t lastLoggedSize = 0; |
| 598 | |
| 599 | // Reset watchdog at start of every upload callback - HTTP parsing can be slow |
| 600 | esp_task_wdt_reset(); |
| 601 | |
| 602 | // Safety check: ensure server is still valid |
| 603 | if (!running || !server) { |
| 604 | LOG_DBG("WEB", "[UPLOAD] ERROR: handleUpload called but server not running!"); |
| 605 | return; |
| 606 | } |
| 607 | |
| 608 | const HTTPUpload& upload = server->upload(); |
| 609 | |
| 610 | if (upload.status == UPLOAD_FILE_START) { |
| 611 | // Reset watchdog - this is the critical 1% crash point |
| 612 | esp_task_wdt_reset(); |
| 613 | |
| 614 | state.fileName = upload.filename; |
| 615 | state.size = 0; |
| 616 | state.success = false; |
| 617 | state.error = ""; |
| 618 | uploadStartTime = millis(); |
| 619 | lastLoggedSize = 0; |
| 620 | state.bufferPos = 0; |
| 621 | totalWriteTime = 0; |
| 622 | writeCount = 0; |
| 623 | |
| 624 | // Get upload path from query parameter (defaults to root if not specified) |
| 625 | // Note: We use query parameter instead of form data because multipart form |
| 626 | // fields aren't available until after file upload completes |
| 627 | if (server->hasArg("path")) { |
| 628 | state.path = server->arg("path"); |
| 629 | // Ensure path starts with / |
| 630 | if (!state.path.startsWith("/")) { |
| 631 | state.path = "/" + state.path; |
| 632 | } |
| 633 | // Remove trailing slash unless it's root |
| 634 | if (state.path.length() > 1 && state.path.endsWith("/")) { |
| 635 | state.path = state.path.substring(0, state.path.length() - 1); |
| 636 | } |
| 637 | } else { |
| 638 | state.path = "/"; |
| 639 | } |
| 640 | |
| 641 | LOG_DBG("WEB", "[UPLOAD] START: %s to path: %s", state.fileName.c_str(), state.path.c_str()); |
| 642 | LOG_DBG("WEB", "[UPLOAD] Free heap: %d bytes", ESP.getFreeHeap()); |
| 643 | |
| 644 | // Create file path |
| 645 | String filePath = state.path; |
| 646 | if (!filePath.endsWith("/")) filePath += "/"; |
| 647 | filePath += state.fileName; |
| 648 | |
| 649 | // Check if file already exists - SD operations can be slow |
| 650 | esp_task_wdt_reset(); |
| 651 | if (Storage.exists(filePath.c_str())) { |
| 652 | LOG_DBG("WEB", "[UPLOAD] Overwriting existing file: %s", filePath.c_str()); |
| 653 | esp_task_wdt_reset(); |
nothing calls this directly
no test coverage detected