ESPAsyncWebServer : how to send a file ?

christianw
Posts: 7
Joined: Fri Apr 21, 2023 8:55 am

ESPAsyncWebServer : how to send a file ?

Postby christianw » Thu Apr 04, 2024 7:38 pm

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

lbernstone
Posts: 1131
Joined: Mon Jul 22, 2019 3:20 pm

Re: ESPAsyncWebServer : how to send a file ?

Postby lbernstone » Thu Apr 04, 2024 9:42 pm

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.

christianw
Posts: 7
Joined: Fri Apr 21, 2023 8:55 am

Re: ESPAsyncWebServer : how to send a file ?

Postby christianw » Fri Apr 05, 2024 4:18 am

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];

lbernstone
Posts: 1131
Joined: Mon Jul 22, 2019 3:20 pm

Re: ESPAsyncWebServer : how to send a file ?

Postby lbernstone » Fri Apr 05, 2024 5:33 am

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

christianw
Posts: 7
Joined: Fri Apr 21, 2023 8:55 am

Re: ESPAsyncWebServer : how to send a file ?

Postby christianw » Fri Apr 05, 2024 6:47 am

I prefer not to save the data permanently but to transmit it either for downloading or for display (using chart.js for example).

boarchuz
Posts: 656
Joined: Tue Aug 21, 2018 5:28 am

Re: ESPAsyncWebServer : how to send a file ?

Postby boarchuz » Fri Apr 05, 2024 6:48 am

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();
}

christianw
Posts: 7
Joined: Fri Apr 21, 2023 8:55 am

Re: ESPAsyncWebServer : how to send a file ?

Postby christianw » Fri Apr 05, 2024 7:13 am

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 :-(

lbernstone
Posts: 1131
Joined: Mon Jul 22, 2019 3:20 pm

Re: ESPAsyncWebServer : how to send a file ?

Postby lbernstone » Fri Apr 05, 2024 8:44 am

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.

zingzog
Posts: 2
Joined: Wed Dec 18, 2024 6:28 pm

Re: ESPAsyncWebServer : how to send a file ?

Postby zingzog » Wed Dec 18, 2024 7:09 pm

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

Who is online

Users browsing this forum: YisouSpider and 2 guests