stream WebDAV downloads in chunks to prevent client disconnects
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "FontInstaller.h"
|
#include "FontInstaller.h"
|
||||||
|
#include "HttpFileStreamer.h"
|
||||||
#include "OpdsServerStore.h"
|
#include "OpdsServerStore.h"
|
||||||
#include "SdCardFontGlobals.h"
|
#include "SdCardFontGlobals.h"
|
||||||
#include "SdCardFontRegistry.h"
|
#include "SdCardFontRegistry.h"
|
||||||
@@ -681,27 +682,12 @@ void CrossPointWebServer::handleDownload() const {
|
|||||||
server->send(200, contentType.c_str(), "");
|
server->send(200, contentType.c_str(), "");
|
||||||
|
|
||||||
NetworkClient client = server->client();
|
NetworkClient client = server->client();
|
||||||
const size_t chunkSize = 4096;
|
bool downloadOk = HttpFileStreamer::streamFileToClient(file, client);
|
||||||
uint8_t buffer[chunkSize];
|
|
||||||
|
|
||||||
bool downloadOk = true;
|
|
||||||
while (downloadOk && file.available()) {
|
|
||||||
int result = file.read(buffer, chunkSize);
|
|
||||||
if (result <= 0) break;
|
|
||||||
size_t bytesRead = static_cast<size_t>(result);
|
|
||||||
size_t totalWritten = 0;
|
|
||||||
while (totalWritten < bytesRead) {
|
|
||||||
esp_task_wdt_reset();
|
|
||||||
size_t wrote = client.write(buffer + totalWritten, bytesRead - totalWritten);
|
|
||||||
if (wrote == 0) {
|
|
||||||
downloadOk = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
totalWritten += wrote;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client.clear();
|
client.clear();
|
||||||
file.close();
|
|
||||||
|
if (!downloadOk) {
|
||||||
|
LOG_DBG("WEB", "Download interrupted while streaming: %s", itemPath.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostic counters for upload performance analysis
|
// Diagnostic counters for upload performance analysis
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "HttpFileStreamer.h"
|
||||||
|
|
||||||
|
#include <Logging.h>
|
||||||
|
#include <esp_task_wdt.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr size_t DOWNLOAD_CHUNK_SIZE = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace HttpFileStreamer {
|
||||||
|
bool streamFileToClient(FsFile& file, NetworkClient& client) {
|
||||||
|
auto* buffer = static_cast<uint8_t*>(malloc(DOWNLOAD_CHUNK_SIZE));
|
||||||
|
if (!buffer) {
|
||||||
|
LOG_ERR("HTTP", "malloc failed: %zu bytes", DOWNLOAD_CHUNK_SIZE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
while (ok) {
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
int result = file.read(buffer, DOWNLOAD_CHUNK_SIZE);
|
||||||
|
if (result < 0) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (result == 0) break;
|
||||||
|
|
||||||
|
size_t bytesRead = static_cast<size_t>(result);
|
||||||
|
size_t totalWritten = 0;
|
||||||
|
while (totalWritten < bytesRead) {
|
||||||
|
esp_task_wdt_reset();
|
||||||
|
size_t wrote = client.write(buffer + totalWritten, bytesRead - totalWritten);
|
||||||
|
if (wrote == 0) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
totalWritten += wrote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
} // namespace HttpFileStreamer
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
|
#include <NetworkClient.h>
|
||||||
|
|
||||||
|
namespace HttpFileStreamer {
|
||||||
|
bool streamFileToClient(FsFile& file, NetworkClient& client);
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <Xtc.h>
|
#include <Xtc.h>
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
|
|
||||||
|
#include "HttpFileStreamer.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
|
const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
|
||||||
constexpr size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]);
|
constexpr size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]);
|
||||||
@@ -330,8 +332,12 @@ void WebDAVHandler::handleGet(WebServer& s) {
|
|||||||
s.send(200, contentType.c_str(), "");
|
s.send(200, contentType.c_str(), "");
|
||||||
|
|
||||||
NetworkClient client = s.client();
|
NetworkClient client = s.client();
|
||||||
client.write(file);
|
bool downloadOk = HttpFileStreamer::streamFileToClient(file, client);
|
||||||
file.close();
|
client.clear();
|
||||||
|
|
||||||
|
if (!downloadOk) {
|
||||||
|
LOG_DBG("DAV", "GET interrupted while streaming: %s", path.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── HEAD ─────────────────────────────────────────────────────────────────────
|
// ── HEAD ─────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user