Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By svideo
#75939 I'm looking to create a web form which will allow a user to upload a selected file and then stream that file out to the serial port as it is being sent by the user's web browser. This is being used to upload firmware to a Nextion LCD panel. In order to initiate the firmware update, I need to send a series of serial commands which include the expected file size of the data to be sent. The file being uploaded may be larger than local storage, so I cannot stage the entire file locally - I must send the file out via serial as the data is sent to me over HTTP. This means I need to know the size of the file to be sent before the transfer begins.

Reviewing the code and associated issues on GitHub for ESP8266WebServer, I find that the HTTPUploadstruct contains "totalSize" and "currentSize", which track the total number of bytes sent so far and the size of the current piece being sent respectively. Thus, "totalSize" will not provide the complete file length until after the file has been completely transferred.

The browsers I've tested (Chrome, FF, and Edge on Win10) all will send the "Content-Length" header when uploading data via HTTP POST. This value can be returned, but it apparently includes the length of the headers being sent as well. As different browsers send different headers, this value will vary when sending the same file from different browsers.

So here's the question: is there any generic way to get the filesize of a file being upload via HTTP before the transfer begins? One solution may be to somehow get the size of the headers being returned so I can subtract that value from the Content-Length to arrive at the size of the file itself, but I'm open to whatever.

Below is a simplified sketch demonstrating a basic upload page and how I'm collecting header and file size information. The resulting sizes will be shown via serial and HTTP. If you upload the same file from different browsers, you'll find different lengths being reported.

Code: Select all#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char *ssid = "WiFiSSID";
const char *password = "WiFiPASSWORD";

ESP8266server server(80);

void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to " + String(ssid));

  server.on("/", HTTP_GET, handleUploadPage);
  server.on("/", HTTP_POST, []() { server.send(200, "text/plain", ""); }, handleUploadTransfer);
  server.onNotFound(handleNotFound);
  const char *headerkeys[] = {"Content-Length"};
  size_t headerkeyssize = sizeof(headerkeys) / sizeof(char *);
  server.collectHeaders(headerkeys, headerkeyssize);
  server.begin();
  Serial.println("HTTP server started at http://" + WiFi.localIP().toString());
}

void loop()
{
  server.handleClient();
}

void handleUploadTransfer()
{
  HTTPUpload &upload = server.upload();
  static long contentLength = 0;
  if (upload.status == UPLOAD_FILE_START)
  {
    Serial.println("UPLOAD_FILE_START");
    Serial.println("upload.filename: " + String(upload.filename));
    Serial.println("hostHeader: " + server.hostHeader());
    Serial.println("header Content-Length: " + server.header("Content-Length"));
    contentLength = server.header("Content-Length").toInt();
    Serial.println("contentLength: " + String(contentLength));
  }
  else if (upload.status == UPLOAD_FILE_WRITE)
  {
    // Serial.println("UPLOAD_FILE_WRITE");
    Serial.println("upload.currentSize: " + String(upload.currentSize));
  }
  else if (upload.status == UPLOAD_FILE_END)
  {
    Serial.println("UPLOAD_FILE_END");
    Serial.println("upload.totalSize: " + String(upload.totalSize));
    Serial.println("contentLength - upload.totalSize = " + String(contentLength - upload.totalSize));
    String httpMessage = "<html><body><h1>Upload test complete</h1><br/><pre>";
    httpMessage += String("upload.filename: " + String(upload.filename) + "\n");
    httpMessage += String("header Content-Length: " + String(contentLength) + "\n");
    httpMessage += String("upload.totalSize: " + String(upload.totalSize) + "\n");
    httpMessage += String("contentLength - upload.totalSize = " + String(contentLength - upload.totalSize) + "\n");
    httpMessage += String("</pre></body></html>");
    server.send(200, "text/html", httpMessage);
  }
}

void handleUploadPage()
{
  Serial.println("Sending upload page");
  String httpMessage = "<html><body><form method='POST' action='/' enctype='multipart/form-data'>";
  httpMessage += String("<h1>File upload test</h1>");
  httpMessage += String("<input name='uploadfile' type='file'><br/><br/>");
  httpMessage += String("<button type='submit'>Upload</button></form></body></html>");
  server.send(200, "text/html", httpMessage);
}

void handleNotFound()
{
  Serial.println("Sending 404");
  server.send(404, "text/plain", "404 not found");
}