diff --git a/src/DirectoryNode.cpp b/src/DirectoryNode.cpp index 730e3fa..2e3180f 100644 --- a/src/DirectoryNode.cpp +++ b/src/DirectoryNode.cpp @@ -578,6 +578,44 @@ String DirectoryNode::getDirectoryStructureHTML() const { return html; } +void DirectoryNode::streamDirectoryHTML(Print &out) const { + if (name == "/") { + out.println(F("")); + delay(0); + } +} + // NEW: Calculate exact required size first size_t DirectoryNode::calculateHTMLSize() const { size_t size = 0; diff --git a/src/DirectoryNode.h b/src/DirectoryNode.h index 6ef825e..6ba20be 100644 --- a/src/DirectoryNode.h +++ b/src/DirectoryNode.h @@ -1,5 +1,6 @@ #ifndef DIRECTORYNODE_H_ #define DIRECTORYNODE_H_ +class Print; #include #include @@ -55,6 +56,7 @@ public: DirectoryNode* advanceToMP3(const uint16_t id); void advanceToFirstMP3InThisNode(); String getDirectoryStructureHTML() const; + void streamDirectoryHTML(Print &out) const; size_t calculateHTMLSize() const; void appendIndentation(String& html, int level) const; DirectoryNode* findFirstDirectoryWithMP3s(); diff --git a/src/main.cpp b/src/main.cpp index 0caed3d..4832fde 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1217,15 +1217,14 @@ server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { webreq_enter(); request->onDisconnect([](){ webreq_exit(); }); - // Stream the response to avoid lifetime issues with temporary Strings and to prevent wrong Content-Length + // Stream the response directly from the directory tree to avoid large temporary Strings AsyncResponseStream* stream = request->beginResponseStream("text/html; charset=UTF-8"); stream->addHeader("Cache-Control", "no-store"); stream->addHeader("Connection", "close"); - // Build HTML under lock, then print into stream + // Generate HTML directly into the stream under lock dir_lock_acquire(); - String html = rootNode.getDirectoryStructureHTML(); + rootNode.streamDirectoryHTML(*stream); dir_lock_release(); - stream->print(html); request->send(stream); }); @@ -1508,12 +1507,8 @@ void loop() if (webreq_cnt > 0 && webrequest_blockings > MAX_WEBREQUEST_BLOCKINGS) { Serial.println("excessive webrequest blocking - suppress reset"); // Avoid resetting server mid-response to prevent mixing headers/body or truncation - server.reset(); - init_webserver(); - webreq_cnt = 0; webrequest_blockings = 0; - server.begin(); } if (audio.isRunning()) diff --git a/web/script.js b/web/script.js index 2931b22..794d6b5 100644 --- a/web/script.js +++ b/web/script.js @@ -58,9 +58,9 @@ setInterval(updateProgress, 500); // Update progress every second if ((this.__url || '').indexOf('/upload') !== -1) { timeoutMs = 600000; // 10 minutes for uploads } else if (this.__method === 'GET') { - timeoutMs = 3500; - } else { timeoutMs = 6000; + } else { + timeoutMs = 8000; } if (isIdempotentGET && inflightKeys.has(key)) {