Page 1 of 1

ESPAsyncWebServer : how to send a file ?

Posted: Thu Apr 04, 2024 7:38 pm
by christianw
I have an ESP32 with an ESPAsyncWebServer which records data in a table (3600 rows maximum)

How do I get the web server to send the data as a CSV file to the browser?
Thanks in advance

Re: ESPAsyncWebServer : how to send a file ?

Posted: Thu Apr 04, 2024 9:42 pm
by lbernstone
If you are just sending a file from the flash, you can use the serveStatic method.
https://github.com/me-no-dev/ESPAsyncWe ... le-by-name
The mime type would be "text/csv".
I would recommend you add a max-age header at the frequency that you are collecting the data.

Re: ESPAsyncWebServer : how to send a file ?

Posted: Fri Apr 05, 2024 4:18 am
by christianw
If you are just sending a file from the flash
Thanks but... datas are in RAM : I have a array to store them :

Code: Select all

struct SDATA {
  float temp;
  long  tmillis;
};

SDATA TabMesures[3600];

Re: ESPAsyncWebServer : how to send a file ?

Posted: Fri Apr 05, 2024 5:33 am
by lbernstone
I assume this is data that you actually want to log anyhow. Write it to a file, and then staticServe that file.
If you want a lightweight data logger that's a bit more sophisticated, take a look at rrdTool

Re: ESPAsyncWebServer : how to send a file ?

Posted: Fri Apr 05, 2024 6:47 am
by christianw
I prefer not to save the data permanently but to transmit it either for downloading or for display (using chart.js for example).

Re: ESPAsyncWebServer : how to send a file ?

Posted: Fri Apr 05, 2024 6:48 am
by boarchuz
CSV is very basic, you could construct it on-the-fly from memory (assuming ESPAsyncWebServer exposes the right stuff to make it possible).

It could be as simple as this (pseudocode obviously):

Code: Select all

http_server.on(HTTP_GET, "/data.csv") {
    response.header.set("Content-Type", "text/csv");
    // TODO: set Content-Length or use chunked encoding
    response.begin();
    for(int row = 0; row < ARRAY_SIZE(TabMesures); ++row) {
        char buffer[20];
        sprintf(buffer, "%.2f", TabMesures[row].temp);
        response.send(buffer);
        response.send(',');
        sprintf(buffer, "%ld", TabMesures[row].tmillis);
        response.send(buffer);
        response.send('\n');
    }
    response.end();
}

Re: ESPAsyncWebServer : how to send a file ?

Posted: Fri Apr 05, 2024 7:13 am
by christianw
I'll try this later, thanks.
But

Code: Select all

sprintf(buffer, "%.2f",...) 
won't work with an ESP32. I'll change to

Code: Select all

dtostrf()
but that's a detail.
On the other hand, I'm more worried about the RAM taken up: about 50 kB for the whole CSV :-(

Re: ESPAsyncWebServer : how to send a file ?

Posted: Fri Apr 05, 2024 8:44 am
by lbernstone
You can do a printf directly into the response method in a for loop. This will stream it, and likely is breaking it into mtu-sized chunks to deliver on the line.

Re: ESPAsyncWebServer : how to send a file ?

Posted: Wed Dec 18, 2024 7:09 pm
by zingzog
I am working on a project that requires sending large files, .png, css, javascript, etc. from an ESP32 server to a client browser.

I extract the file content as bytes, store it as constant arrays in flash, and simply use the constant array as the data source in the server's send command, no RAM requirement. I wondered if a similar mechanism would work for you.

I created a char array as a variable, not constant.

Code: Select all

#define NUMVALUES 3600
#define CHARSPERVALUE 36
static char tabvals_csv[NUMVALUES * CHARSPERVALUE] = "";
and filled it with values created using sprintf.

Code: Select all

void fillTabMesures(){
  int n;
  char tabvalue[CHARSPERVALUE] = "";
  for (int i=0;i<(NUMVALUES);i++){
    float value = float(i)/100.0;
    unsigned long  tnow = millis();
    n = sprintf(tabvalue,"%7.2f,%22lu,\n", value, tnow);
    strcat(tabvals_csv,tabvalue);
  }
}
I set up a callback with:

Code: Select all

    server.on("/tabvals.csv",handletabvals);
and used the send command with the array as a parameter to send the file

Code: Select all

void handletabvals(){
    server.send(200, "text/csv", tabvals_csv);
}
Now, if I request http://buttons.local/tabvals.csv from my server using firefox on my PC I get a file save dialog asking where to save the file. The file loads to my spreadsheet program and gives output of the form:

Code: Select all

   0.00,                   793,
   0.01,                   793,
   0.02,                   793,
   0.03,                   793,
   0.04,                   793,
The disadvantage is that the array is larger than the raw values.
The advantages are:
- that the data don't have to be processed on the fly, they are sent directly by the server.
- no additional buffering/storage is needed to process the raw data to csv strings.

I am using ESP32-S3-DevKitC-1, and I don't have a problem with sprintf.

Andy