Uploading text file to WIFI1010 via web browser

Hi Folks. I'm using a web browser as a GUI dashboard for my MKRWIFI1010 project. It works great and I've got a ton of HTML / CSS code embedded in my c++ Arduino code along with a little JavaScript. I'm able to download a .txt file from the Arduino (my code creates the .txt file on the fly, it's not stored anywhere) using the following code:

client.print("<a href=\"Round_Results.txt\" download><button type=\"button\">Save Round Results</button>");
              client.print("<src=\"Round_Results.txt\">");
              client.print("</a>");

Then on the server (Arduino) side I'm parsing the commands from the client (browser). When the "Save Round Results" button is clicked in the browser, it triggers the following function:

else if (currentLine.endsWith("GET /Round_Results.txt")) {
          client.print("Place\tComp\tRound\tRace\tLane\tDriver\tReact\tET\tMPH\r");
          for (int x = 1; x <= raceNumber; x++) {
            client.print(String(x) + "\t");
            for (int y = 0; y <= 7; y++) {
              client.print(allTextArray[x][y] + "\t");
            }
            client.print("\r");
          }
          client.println();
          break; 
        }

This works just fine and creates a new .txt file on my test computer. The big question is, how can I reverse the process and upload a .txt file from my test computer to the Arduino using the browser? I got to the point of the browser opening a file upload dialog box, selecting a file and submitting it for upload. I want to store this file in an array. I'm monitoring the data coming from the browser using the following code:

 WiFiClient client = server.available(); 
  if (client) {                             
    //   Serial.println("new client"); 
    String currentLine = ""; 
    while (client.connected()) {
      if (client.available()) { 
        char c = client.read(); 
         if (Serial) {
                  Serial.write(c);
         }
        if (c == '\n') {    
          if (currentLine.length() == 0) {

            client.print("<!DOCTYPE html>");
            client.print("<html lang=\"en

When I click the submit button to send the file, I don't see any incoming data in client.available(). This is the code for the button that I'm clicking for upload:

client.print("<form action=\"upload.php\" method=\"post\" enctype=\"multipart/form-data\">");
client.print("Select file to upload");
client.print("<input type=\"file\" id=\"myFile\" name=\"filename\">");
client.print("<input type=\"submit\" value=\"Upload File\" name=\"Submit\">");
client.print("</form>");

I get the response on the server side that says "POST/ upload.php multipart etc.". And I understand that upload.php calls a php script function that I need to emulate. But here is where I get stuck. Ideas anyone?

It has to be a bit more involved on the client side, see <input type="file"> - HTML: HyperText Markup Language | MDN

It looks like I have what is required on the client side. As far as I can tell anything else is optional (allowed file types, etc). I believe it's the server side that's missing some code. I think I need to emulate the PHP functions fopen(), fread(), fclose(), etc. I have no insight into PHP libraries so I can't come up with emulation on my own.

Indeed, should be enough. This is what I used

  client.println(F("<form action=\"upload\" method=\"post\" enctype=\"multipart/form-data\">"));
  client.println(F("<div>"));
  client.println(F("<label for=\"chooser\">Choose file to upload</label>"));
  client.println(F("<input type=\"file\" id=\"chooserId\" name=\"chooser\" accept=\"*\">"));
  client.println(F("</div>"));
  client.println(F("<div>"));
  client.println(F("<button>Submit</button>"));
  client.println(F("</div>"));
  client.println(F("</form>"));

when I select a file and then hit submit, my arduino gets a post request for /upload (as this is the action documented in the HTML) and the content you get looks like this

POST /upload HTTP/1.1
Host: 10.86.1.182
Origin: http://10.86.1.182
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWIcq9NKPyWkWvBPy
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6 Safari/605.1.15
Referer: http://10.86.1.182/
Content-Length: 4831
Accept-Language: fr-FR,fr;q=0.9

------WebKitFormBoundaryWIcq9NKPyWkWvBPy
Content-Disposition: form-data; name="chooser"; filename="sketch_aug07c.ino"
Content-Type: application/octet-stream

[[----------------------]]
[[   HERE THE CONTENT   ]]
[[     OF YOUR FILE     ]]
[[----------------------]]

------WebKitFormBoundaryWIcq9NKPyWkWvBPy--

so you would need to extract whatever is in between the matching pair of ------WebKitFormBoundaryXXX after the header

Hmm. This is what I get on Submit:

POST /upload HTTP/1.1
Host: 192.168.4.46
Connection: keep-alive
Content-Length: 321
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.4.46
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhBnbMDWX6OhYSCjT
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.4.46/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

Which is slightly different from your results. Most importantly is the missing file! Would you mind sharing the server code that gave you the above results? I may be unintentionally filtering the data coming from the client. Thank you!

Ah! I'm making progress. I made this my "upload" function and now it works perfectly:

        if (currentLine.endsWith("POST /upload")) {
          while (client.connected()) {
            if (client.available()) {
              c = client.read();
              Serial.write(c); 
            }
          }
        }

I had been waiting for the client.read() at the top of my loop to get the data instead of doing it immediately with the function. Thank you so much. I'm fairly new to Arduino, C++, HTML / CSS, Java, etc., and I appreciate your help and patience.

Seems you were printing only the headers. Printing everything will get you the content

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