Sending png image from browser to esp32 server

I'm not looking for someone to code this for me, but if you can point me in the direction of public domain code. :slight_smile: Unlikely.

I have an image on a browser canvas. I can get the canvas image data, URL encoded, base64 encoded, or even png/jpeg image data.

I need a solution to send the png file to ESP32. If I send something URL/base64 encoded to the ESP32, I need to have the memory on the ESP32 to decode it....yes?

I've thought about chunking the png file and sending small encoded chunks, but how would one go about that? keeping the sequence correct when decoding and rebuilding the png file?

Whats the best way to send multiple chunks and not over load the ESP32? Recommendation on ESP libraries to use?

I have the browser (javascript) side pretty much worked out (but I'm open to suggestion), it's the ESP32 side of things I need the help.

Any help and guidance appreciated! Thank you.

if you use ESPAsyncWebServer it's pretty simple

try this

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

const char*   ssid = "xxxxxxxx";
const char*   password = "xxxxxxxx";
AsyncWebServer server(80);

// Embedded HTML code as a raw string literal
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
    <title>File Upload</title>
</head>
<body>
    <h2>Upload a file</h2>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="fileToUpload" id="fileToUpload">
        <input type="submit" value="Upload File" name="submit">
    </form>
</body>
</html>
)rawliteral";

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("WiFi Failed!\n");
    while (true) yield();
  }
  Serial.println("Connected to WiFi");

  Serial.print("Open URL http://"); Serial.println(WiFi.localIP());

  
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html);
  });

  server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
    request->send(200);
  }, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
    if (!index) {
      Serial.print("Receiving file: ");
      Serial.println(filename);
    }
    for(size_t i = 0; i < len; i++){
      Serial.write(data[i]);
    }
    if(final) {
      Serial.println("\n-----------\nFile upload completed");
    }
  });

  server.begin();
}

void loop() {}

change the xxxxxx to match your wireless network details
compile and upload to your ESP32, open the Serial monitor at 115200 bauds
You'll see something like

Connected to WiFi
Open URL http://10.116.1.22

Connect to the url printed in the serial monitor (here http://10.116.1.22)

you'll see a simple web interface (localised, my system runs in French)

image

click on the button to select a file from your file selector in the web browser

the file name will show next to the button

click the image button

you'll see in the serial monitor the bytes coming in.

the callback method is using chunks so if you want to save the file in RAM on the ESP32 you'll have to do that in the lambda function which will be called a number of time (until the final flag is set)

Thank you for your reply. It's not exactly what I need.

The data needs to come from a HTML canvas and not a file upload. A blob maybe?

Also, the chunked data can be received with ESPAsyncWebServer callbacks, but you cant decode on the fly this way, the entire file is needed.

It would be great if those two things can be solved. Thank you again!

it's very similar and ESPAsncWebServer makes it easy to handle either file uploads or just extracting content from the body of a response.

as this coule be helpful in the long run, I posted that as a tutorial, see

Hope this helps!

--
PS:

instead of printing each byte as they come in (if multipart) you need to use memcpy() and the parameters of the current function call to know where to dump the bytes into your global buffer. Once the last function call will have occurred, your buffer will be ready to use.

Thank you J-M-L Jackson! I've seen parts of your tutorial other places, but nothing as well put together as your example. I was able to make a working model for my needs. I'm sure many others will find this tutorial helpful.

You tutorial is great!

cool

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.