<form id='flash' method='POST' action='/flash_firmware' enctype='multipart/form-data'>
<!--need to upload filesize first because Content-Length [request->contentLength()] isn't the actual file size-->
<input id='filesize' name="filesize" value="0" style="display:none">
<input id='file' type='file' name='update'>
<p></p>
<input id='flash_btn' type='submit' value='Flash'>
</form>
<script>
document.querySelector('form').addEventListener('submit', (e) => {
document.getElementById('filesize').value = document.getElementById('file').files[0].size;
});
</script>
Hi!
I want to write a file upload handler class.
My current class is
class UpdateMasterRequestHandler : public AsyncWebHandler {
public:
UpdateMasterRequestHandler(/* args */) { }
virtual ~UpdateMasterRequestHandler() { }
bool canHandle(AsyncWebServerRequest *request);
void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final);
};
canHandle
returns true, but handleUpload
never gets called.
What am I doing wrong?
bool UpdateMasterRequestHandler::canHandle(AsyncWebServerRequest *request) {
bool forMe = request->url() == "/api/UpdateMaster"
&& request->method() == HTTP_POST
&& request->multipart();
if (forMe) logDebugln("UpdateMasterRequestHandler!");
return forMe;
}
void UpdateMasterRequestHandler::handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) {
if (index == 0) {
logDebug("UploadStart: ");
logDebugln(filename);
request->_tempFile = SPIFFS.open("master.hex", "w");
}
if (len > 0) {
request->_tempFile.write(data, len);
}
if (final) {
logDebug("UploadEnd: ");
logDebugln(filename);
request->_tempFile.close();
request->send(200, MIME_TYPE_PLAIN_TEXT, "Upload complete!");
}
}
HTML:<form id="masterUpdateForm" action="/api/UpdateMaster" method="POST" enctype="multipart/form-data">
Firmware: <input type="file" name="file" accept="*.hex">
<button type="submit">Update</button>
</form>
class UpdateMasterRequestHandler : public AsyncWebHandler {
public:
UpdateMasterRequestHandler(/* args */) { }
virtual ~UpdateMasterRequestHandler() { }
virtual bool canHandle(AsyncWebServerRequest *request) override final;
virtual void handleRequest(AsyncWebServerRequest *request) override final;
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final;
};
Backtrace: 0x4000c3f0:0x3ffd1380 0x400db076:0x3ffd13a0 0x400db192:0x3ffd13c0 0x400d7ad1:0x3ffd13e0 0x400d6192:0x3ffd1450 0x400d60f5:0x3ffd1490 0x400d145d:0x3ffd14b0 0x4015188f:0x3ffd14f0 0x400d9309:0x3ffd1510 0x400d6df1:0x3ffd1560 0x400d6eb5:0x3ffd15a0 0x400d7105:0x3ffd15f0 0x4014b7b1:0x3ffd1610 0x4014b82d:0x3ffd1650 0x4014bed6:0x3ffd1670 0x4008a286:0x3ffd16a0
#0 0x4000c3f0:0x3ffd1380 in ?? ??:0
#1 0x400db076:0x3ffd13a0 in String::move(String&) at C:\Users\OnurNP.platformio\packages\framework-arduinoespressif32\cores\esp32/WString.cpp:857
#2 0x400db192:0x3ffd13c0 in String::operator=(String&&) at C:\Users\OnurNP.platformio\packages\framework-arduinoespressif32\cores\esp32/WString.cpp:857
#3 0x400d7ad1:0x3ffd13e0 in AsyncBasicResponse::_respond(AsyncWebServerRequest) at lib\ESPAsyncWebServer\src/WebResponses.cpp:699
#4 0x400d6192:0x3ffd1450 in AsyncWebServerRequest::send(AsyncWebServerResponse) at lib\ESPAsyncWebServer\src/WebRequest.cpp:797
#5 0x400d60f5:0x3ffd1490 in AsyncWebServerRequest::send(int, String const&, String const&) at lib\ESPAsyncWebServer\src/WebRequest.cpp:797
#6 0x400d145d:0x3ffd14b0 in handleRoot(AsyncWebServerRequest) at src/main.cpp:289
#7 0x4015188f:0x3ffd14f0 in std::_Function_handler<void (AsyncWebServerRequest), void ()(AsyncWebServerRequest)>::_M_invoke(std::_Any_data const&,
AsyncWebServerRequest*&&) at c:\users\onurnp.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0/functional:1871
#8 0x400d9309:0x3ffd1510 in std::function<void (AsyncWebServerRequest*)>::operator()(AsyncWebServerRequest*) const at lib\ESPAsyncWebServer\src/StringArray.h:73
(inlined by) AsyncCallbackWebHandler::handleRequest(AsyncWebServerRequest*) at lib\ESPAsyncWebServer\src/WebHandlerImpl.h:132
#9 0x400d6df1:0x3ffd1560 in AsyncWebServerRequest::_parseLine() at lib\ESPAsyncWebServer\src/WebRequest.cpp:797
#10 0x400d6eb5:0x3ffd15a0 in AsyncWebServerRequest::_onData(void, unsigned int) at lib\ESPAsyncWebServer\src/WebRequest.cpp:797
#11 0x400d7105:0x3ffd15f0 in std::_Function_handler<void (void, AsyncClient, void, unsigned int), AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer, AsyncClient)::{lambda(void, AsyncClient, void, unsigned int)#8}>::_M_invoke(std::_Any_data const&, void&&, AsyncClient*&&, std::_Any_data const&, unsigned int&&) at lib\ESPAsyncWebServer\src/WebRequest.cpp:797
(inlined by) _M_invoke at c:\users\onurnp\.platformio\packages\toolchain-xtensa32@2.50200.97\xtensa-esp32-elf\include\c++\5.2.0/functional:1871
#12 0x4014b7b1:0x3ffd1610 in std::function<void (void*, AsyncClient*, void*, unsigned int)>::operator()(void, AsyncClient, void*, unsigned int) const at lib\AsyncTCP\src/AsyncTCP.cpp:1039
(inlined by) AsyncClient::_recv(tcp_pcb*, pbuf*, signed char) at lib\AsyncTCP\src/AsyncTCP.cpp:934
#13 0x4014b82d:0x3ffd1650 in AsyncClient::_s_recv(void, tcp_pcb, pbuf, signed char) at lib\AsyncTCP\src/AsyncTCP.cpp:1039
#14 0x4014bed6:0x3ffd1670 in _async_service_task(void) at lib\AsyncTCP\src/AsyncTCP.cpp:1039
(inlined by) _async_service_task at lib\AsyncTCP\src/AsyncTCP.cpp:197
#15 0x4008a286:0x3ffd16a0 in vPortTaskWrapper at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Using AsyncWebServer on ESP32 I'm getting frequent Guru Meditation Errors:
Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400d7e7c PS : 0x00060430 A0 : 0x800d7f1a A1 : 0x3ffb1f00
A2 : 0x3ffd31bc A3 : 0x3ffd2f84 A4 : 0x00000026 A5 : 0x3ffd2caa
A6 : 0x00000a0d A7 : 0x3a617461 A8 : 0x800d7e88 A9 : 0x3ffb1ee0
A10 : 0xe0088080 A11 : 0x00000026 A12 : 0x00000026 A13 : 0x00000026
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0xe0088088 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
ELF file SHA256: 0000000000000000
Backtrace: 0x400d7e7c:0x3ffb1f00 0x400d7f17:0x3ffb1f20 0x400d7f37:0x3ffb1f40 0x400d7f8d:0x3ffb1f60 0x400d17d3:0x3ffb1f90 0x400df329:0x3ffb1fb0 0x40089afa:0x3ffb1fd0
the backtrace shows
Decoding 7 results
0x400d7e7c: AsyncEventSourceClient::_runQueue() at c:\arduinoideportable\portable\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0/functional line 1858
0x400d7f17: AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage) at c:\arduinoideportable\portable\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0/functional line 1858
0x400d7f37: AsyncEventSourceClient::write(char const, unsigned int) at c:\arduinoideportable\portable\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0/functional line 1858
0x400d7f8d: AsyncEventSource::send(char const, char const, unsigned int, unsigned int) at c:\arduinoideportable\portable\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0/functional line 1858
0x400d17d3: loop() at C:\ArduinoIDEPortable\portable\sketchbook\ESP32\SolarLoggerJune12/SolarLoggerJune12.ino line 151
0x400df329: loopTask(void*) at C:\ArduinoIDEPortable\portable\packages\esp32\hardware\esp32\1.0.6\cores\esp32/main.cpp line 23
0x40089afa: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 355 (discriminator 1)
referring to this line in my code
151: events.send( mycWatts , "cwatts", millis());
It doesntt happen every time but its realy giving me a headache. Any ideas?
button.addEventListener("click", async(_) => {
try {
const response = await fetch("board", {
method: "post",
body: {
"id":1,
"t1":2,
"t2":3
}
});
console.log("Completed!", response);
} catch (err) {
console.error(`Error: ${err}`);
}
}); `
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Content-Type");