Arduino webserver needs to force web page refresh after downloading csv file

This is a little different to the normal for this sort of question I'm using a Leonardo as data logger and Web server that is recording data to the SD card on the ethernet shield.
I'm developing a web page running on the Arduino that allows me to download the record files. Most of the HTML is in a file on the SD card which the sketch reads and sends to the web, along the way it fills in the current data file name to a "myfile.csv" button and puts all available data file names into an HTML table for selection/download/ or deletion

In the process of downloading the required data file the first few bytes get over written with the current data/time etc. so that the user can see the state of the record and when the last download was made.

Because of this change when a selected file is downloaded the table on the parent web page that lists all the files needs to be updated after the download. The big problem is that <a href = ...... frezzes any <meta refresh that is in the web page header. Looking at web sites like 'Stackoverflow' this Appears to be a well known limitation of HTML and I have not found any sensible suggestions that will make the web page refresh.

I've tried several things and the best I've achieved is with the web page is the following bit of HTML which I put where I want the user to be able to download a data file.

<form name = "currentFile" method = "POST" id = "DownldFile" action="downld2.htm">
            <input type = "submit" id = "setfile" name = "uPdATEF8" value = "myfile.csv" readonly />

Coupled with the following code on the Leo. This first bit is the standard decoding of POST or GET requests sent to the Arduino

 byte requestType = 0;
  char c;
  client = server.available();
  if (client){   
    while (client.connected()){
      if (client.available()) {
        memset(fileRequest, 0 ,sizeof(fileRequest)); //clear the inputBuffer
        if (client.readBytesUntil('/',fileRequest,MAX_PAGE_NAME_LEN)){
          if (strcmp(fileRequest,"GET ") == 0){
          requestType = 1 ; //search for 'GET'
          if (strcmp(fileRequest,"POST ") == 0){
          requestType = 2;  //search for 'POST'
        //gather what comes after the '/'
        memset(fileRequest, 0 ,sizeof(fileRequest)); //clear the inputBuffer
        //EofN = 0;
          if( client.find("") ){
            fileBufferLen = 0;
            *fileRequest = 0;
            while(fileBufferLen < MAX_PAGE_NAME_LEN){//need to sort out getting second parameter to save
              c =;// the need for two download HTML files
              if( c == 0 ){
                fileBufferLen = 0;   // timeout returns 0 !
              else if((c == 32)||(c == 63)) {  // space character or ?
                fileRequest[fileBufferLen] = 0; // terminate the string
                fileRequest[fileBufferLen++] = c;
            fileRequest[fileBufferLen] = 0;
            // Note: inputBuffer full before the closing post_string encountered
          else fileBufferLen = 0;    //failed to find the prestring
        }//end if(client.readBytes
        client.find("\r\n\r\n");//have to find the blank line & make sure we read to the end
        if (requestType == 2){ //do a POST
          //Serial.println (requestType);
          breakTime(systime);    //ready to show date and time in file 
          }//end if (requestType == 2)
        // GET or POST Give the string asked for
        // or if no file name give index.htm
        if (fileBufferLen == 0) {
        }//end if
        breakTime(systime);    //ready to show date and time on page
      }//end  (client.available ....
  }//end if (client)..  
} //end 'loop' 

After that I've separated out the code that sends the response to GET request into a 'sendFile(..) function and the parseing of a POST request into a actionUpDate() function, which is given below

void actionUpDate()
  char c = 0;
  char actionFile [13];
  while (c!=-1) {
  //if client sends a values for the file filter or thermostat take them/it
  if (client.findUntil("PdATE","\r\n\r\n")){ //have to find the blank line & make sure we read to the end
    //Serial.println("found update");
    //get next 2 byte
    c =;    //get the next one to determin which Array to change
    int  i = client.parseInt(); //get next char which should be pointer to which value to change
          if  (c == 'F') {    //this is 'F' for the file filter
            if ( == '=' ){ // should be the '=' sign ascii 61
              ///do things with $FX fltrLastFile here
              //Serial.println (i);
              switch (i){
                case 5:
                  memset(fltrFirstFile, 0 ,sizeof(fltrFirstFile)); //clear the inputBuffer
                case 6:
                  memset(fltrLastFile, 0 ,sizeof(fltrLastFile)); //clear the inputBuffer
                case 7:
                  memset(actionFile, 0 ,sizeof(actionFile)); //clear the inputBuffer
                  sd.remove (actionFile);
                case 8:
                  //Serial.print ("case8");
                  memset(actionFile, 0 ,sizeof(actionFile)); //clear the inputBuffer
                  sendFile (actionFile);
                  client.print ("\r\n\r\n");
              }//end switch (i)
            else return;              //'=' sign not found input corrupt
      }//end  if (client.findUntil("uPdATE".....
      c =; //check were at the end?   
  } //end while 

This works, but not quite.
The Arduino gets the request keeps the file name of the page in the POST request, sends the rest of the update info to the actionUpDate function which in turn sorts out the various specific types of update, when it gets to case 8 for downloading a file it then finds the name of the CSV file that is wanted and sends this request on to the sendFile function. Once that has been done it returns to the original calling code and then sends the the HTML file called for.

In the above 'downld2.htm' is the parent web page on the SD card and 'uPdADTEF8' is the pointer that the code on the Arduino uses to know that it has to send the requested CSV file. The 'myfile.csv' is a place holder which the Arduino fills in with the relevant file name as it sends the web page to the client.

This nearly works but in Edge and Safari, both the myfile.csv is downloaded and the page HTML is sent BUT 'myfile.CSV' gets called 'downld2' on the download icon in Edge and disappears in Safari.

I'm beginning to think that I need to include both 'C' code on the Arduino and 'Java scripts' in the HTML but what I need is beyond me at the moment.

Has anybody tackled this sort of problem before? I've not found anything on the forum so far.

the page with your log entries (and last download time) seems to me not to be static. Therefore I wouldn't host this page on SD but in FLASH and just add new information during runtime.

if you want to update the content of a cell in your table after the Start of the download, I would rather do a fetch data with Fetch API (or old style AJAX) and just update the cell (with JavaScript) - but not reload the whole page.

Its true that the Log files for the current month are not static during the current month, they are growing with new data every few seconds. However as a new set of files are started at the turn of the calendar the data on the older ones is static there after. The extra info put in the files at down load time is also dynamic and needs to be preserved in the downloaded files.

In any event this is a big program and I have had to create a special board in Boards.txt which eliminates the boot loader and the serial connectivity to access all 32K of the programme space. On compile I have 900 bytes left!! Before anybody suggests using a bigger chip like a Mega I need to point out that this is a second version of this project and a different board wont fit in the existing box with the rest of the hardware!

I did look at using Fetch for the update but this has a number of problems. As the table of file names/attributes is created dynamically by the Leo from the directory on the SD card I would some how have to give all the cells to be updated an HTML ID which would not be the same on a a new call to that page so putting the right update in the right place every time would be very complex, secondly I would still have to solve the problem of making a single button click do two things and call the downloaded file by the right name

poor argument. Consider the Mega 2560 Pro it's more or less the same size like an Uno.

However, I don't see the point to upgrade if you have 900 bytes flash left.

It's only about one page and a dynamic table to make your downloads accessible. Or I totally missed your point. Can you show a picture of your current download page? Or a Mokup how it should look like?

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