简体   繁体   中英

How to enable the server to automatically download files using arduino for ESP32 WebServer without using SPIFFS and instead using SDcard file



#include <WiFiClient.h>
#include <WebServer.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include <SPI.h>
#include <SD.h>


String serverIndex = "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
    "<input type='file' name='update'>"
    "<input type='submit' value='Upload'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
    "e.preventDefault();"
      "var form = $('#upload_form')[0];"
      "var data = new FormData(form);"
      " $.ajax({"
            "url: '/update',"
            "type: 'POST',"               
            "data: data,"
            "contentType: false,"                  
            "processData:false,"  
            "xhr: function() {"
                "var xhr = new window.XMLHttpRequest();"
                "xhr.upload.addEventListener('progress', function(evt) {"
                    "if (evt.lengthComputable) {"
                        "var per = evt.loaded / evt.total;"
                        "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
                    "}"
               "}, false);"
               "return xhr;"
            "},"                                
            "success:function(d, s) {"    
                "console.log('success!')"
           "},"
            "error: function (a, b, c) {"
            "}"
          "});"
"});"
"</script>";

const char* ssid = "Entrib-Main";
const char* password = "shopWorx110T";

WebServer server(80);
File root;
bool opened = false;

String printDirectory(File dir, int numTabs) {
  String response = "";
  dir.rewindDirectory();

  while(true) {
     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');   // we'll have a nice indentation
     }
     // Recurse for directories, otherwise print the file size
     if (entry.isDirectory()) {
       printDirectory(entry, numTabs+1);
     } else {
       response += String("<a href='") + String(entry.name()) + String("'>") + String(entry.name()) + String("</a>") + String("</br>");
     }
     entry.close();
   }
   return String("List files:</br>") + response + String("</br></br> Upload file:") + serverIndex;
}

void handleRoot() {

  root = SD.open("/");
  String res = printDirectory(root, 0);
  server.send(200, "text/html", res);
}


bool loadFromSDCARD(String path){
  path.toLowerCase();
  String dataType = "text/plain";
  if(path.endsWith("/")) path += "index.htm";

  if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
  else if(path.endsWith(".jpg")) dataType = "image/jpeg";
  else if(path.endsWith(".txt")) dataType = "text/plain";
  else if(path.endsWith(".zip")) dataType = "application/zip";  
  else if(path.endsWith(".bin")) dataType = "text/plain"; 
  Serial.println(dataType);
  File dataFile = SD.open(path.c_str());

  if (!dataFile)
    return false;

  if (server.streamFile(dataFile, dataType) != dataFile.size()) {
    Serial.println("Sent less data than expected!");
  }

  dataFile.close();
  return true;
}

void handleNotFound(){

  if(loadFromSDCARD(server.uri())) return;
  String message = "SDCARD Not Detected\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  Serial.println(message);
}

void setup(void){
  SPI.begin(14, 2, 15, 13);
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  //use IP or iotsharing.local to access webserver
  if (MDNS.begin("iotsharing")) {
    Serial.println("MDNS responder started");
  }
  if (!SD.begin()) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  //handle uri  
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);




  /*handling uploading file */
  server.on("/update", HTTP_POST, [](){
    server.sendHeader("Connection", "close");
  },[](){
    HTTPUpload& upload = server.upload();
    if(opened == false){
      opened = true;
      root = SD.open((String("/") + upload.filename).c_str(), FILE_WRITE);  
      if(!root){
        Serial.println("- failed to open file for writing");
        return;
      }
    } 
    if(upload.status == UPLOAD_FILE_WRITE){
      if(root.write(upload.buf, upload.currentSize) != upload.currentSize){
        Serial.println("- failed to write");
        return;
      }
    } else if(upload.status == UPLOAD_FILE_END){
      root.close();
      Serial.println("UPLOAD_FILE_END");
      opened = false;
    }
  });
  server.begin();
  Serial.println("HTTP server started");
}

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

This is a working code to obtain the sd card data from ESP32 TTGO T1 module on to the web server and will display all the files on the sd card directory and would download the file once you click on the file name. However, when I tried to modify the code to enable the server to download the SD card file automatically without having to click on the file name it was not working. I tried the same by replacing SPIFFS in the async web server code with SD but it was not giving any output on the server

I have attached the code for AsyncWebServer below which was working perfectly with SPIFFS however didn't work with SD .

#include "WiFi.h"
#include "SPIFFS.h"
#include "ESPAsyncWebServer.h"
#include "SPI.h"
#include "SD.h"

const char* ssid = "Entrib-Main";
const char* password =  "shopWorx110T";

AsyncWebServer server(80);
File root;
String serverIndex = "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
    "<input type='file' name='update'>"
    "<input type='submit' value='Upload'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
    "e.preventDefault();"
      "var form = $('#upload_form')[0];"
      "var data = new FormData(form);"
      " $.ajax({"
            "url: '/update',"
            "type: 'POST',"               
            "data: data,"
            "contentType: false,"                  
            "processData:false,"  
            "xhr: function() {"
                "var xhr = new window.XMLHttpRequest();"
                "xhr.upload.addEventListener('progress', function(evt) {"
                    "if (evt.lengthComputable) {"
                        "var per = evt.loaded / evt.total;"
                        "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
                    "}"
               "}, false);"
               "return xhr;"
            "},"                                
            "success:function(d, s) {"    
                "console.log('success!')"
           "},"
            "error: function (a, b, c) {"
            "}"
          "});"
"});"
"</script>";


String printDirectory(File dir, int numTabs) {
  String response = "";
  dir.rewindDirectory();

  while(true) {
     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       //Serial.println("**nomorefiles**");
       break;
     }
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');   // we'll have a nice indentation
     }
     // Recurse for directories, otherwise print the file size
     if (entry.isDirectory()) {
       printDirectory(entry, numTabs+1);
     } else {
       response += String("<a href='") + String(entry.name()) + String("'>") + String(entry.name()) + String("</a>") + String("</br>");
     }
     entry.close();
   }
   return String("List files:</br>") + response + String("</br></br> Upload file:") + serverIndex;
}

void setup(){
  Serial.begin(115200);
  SPI.begin(14, 2, 15, 13);

  if(!SPIFFS.begin()){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
  }

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println(WiFi.localIP());

  server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){
    SPI.begin(14, 2, 15, 13);
    root = SD.open("/");
    String res = printDirectory(root, 0);
    request->send(SD, "/data/sample.bin", "text/html", true);
  });

   root = SD.open("/");
   String res = printDirectory(root, 0);

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
   root = SD.open("/");
   String res = printDirectory(root, 0);
    request->send(200, "text/html", res);
  }); 

  server.begin();
}

void loop(){}

Could anyone please suggest any changes to be made to this code to enable it to work for SD card files to auto download from a server or if you have any other working code for the same issue it would be appreciated. Thank You:)

 // Define CS pin for the SD card module
 #define SD_CS 5  


 server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){
 SD.begin(SD_CS);  
 if(!SD.begin(SD_CS)) {
 Serial.println("Card Mount Failed");
 logmessage = "Card Mount Failed"; 
 return;
 }  
 File file = SD.open("/data.txt");
 if(!file){
 //Serial.println(" Failed to open file for reading");
 return;
 }
 request->send(file, "/data.txt", "text/xhr", true);
 Serial.print("Recieved data.txt request from client IP ");
 Serial.println(request->client()->remoteIP());
 });

I'm not sure it solves shalom-daniel's problem.

I just wanted to show how i am downloading a file named data.txt from sd card connected to esp32 to client.

CS is connected to io 5 on Esp32.

SCK is connected to io 18 on Esp32.

MOSI is connected to io 23 on Esp32.

MISO is connected to io 19 on Esp32.

It might look a little strange to start with SD.end, but that's the only way i can make it work right.

server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){
SD.end();
SD.begin(SD_CS); 
File file = SD.open("/data.txt");
if(!SD.begin(SD_CS)) {
Serial.println("Card Mount Failed");
request->send (200, "text/html", "<H1>Card Mount Failed</h1>");

} 
else  
if(!file){
Serial.println("Failed to open file for reading");
request->send (200, "text/html", "<H1>Failed to open file for reading</h1>");

}
else{
request->send(file, "/data.txt", "text/xhr", true);
Serial.print("Recieved data.txt request from client IP ");
Serial.println(request->client()->remoteIP());
} 
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM