如何使服务器使用 arduino for ESP32 WebServer 自动下载文件而不使用 SPIFFS 而是使用 SDcard 文件 [英] How to enable the server to automatically download files using arduino for ESP32 WebServer without using SPIFFS and instead using SDcard file

查看:38
本文介绍了如何使服务器使用 arduino for ESP32 WebServer 自动下载文件而不使用 SPIFFS 而是使用 SDcard 文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<预><代码>#include #include #include <WiFi.h>#include #include #include 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'>""<输入类型='文件'名称='更新'>""<输入类型='提交'值='上传'>"</表单>"<div id='prg'>进度:0%</div>"<脚本>""$('form').submit(function(e){"e.preventDefault();""var form = $('#upload_form')[0];""var data = new FormData(form);"" $.ajax({"网址:'/更新',"类型:'POST',"数据:数据,"内容类型:假,"过程数据:假,"xhr:函数(){""var xhr = new window.XMLHttpRequest();""xhr.upload.addEventListener('progress', function(evt){"如果(evt.lengthComputable){"每个变量 = evt.loaded/evt.total;""$('#prg').html('progress:' + Math.round(per*100) + '%');"}"}, 错误的);"返回xhr;""},"成功:功能(d,s){""console.log('成功!')""},"错误:函数(a,b,c){"}""});""});""</脚本>";const char* ssid = "Entrib-Main";const char* 密码 = "shopWorx110T";网络服务器(80);文件根;布尔打开 = 假;字符串打印目录(文件目录,int numTabs){字符串响应 = "";dir.rewindDirectory();而(真){文件入口 = dir.openNextFile();如果(!条目){//没有更多文件//Serial.println("**nomorefiles**");休息;}for (uint8_t i=0; i

这是从 ESP32 TTGO T1 模块获取 sd 卡数据到 Web 服务器的工作代码,将显示 sd 卡目录中的所有文件,并在您点击后下载文件在文件名上.但是,当我尝试修改代码以使服务器能够自动下载 SD 卡文件而无需单击文件名时,它不起作用.我通过用 SD 替换异步 Web 服务器代码中的 SPIFFS 来尝试相同的方法,但它没有在服务器上提供任何输出

我在下面附上了 AsyncWebServer 的代码,它与 SPIFFS 完美配合,但不适用于 SD.

#include "WiFi.h"#include "SPIFFS.h"#include "ESPAsyncWebServer.h"#include "SPI.h"#include "SD.h"const char* ssid = "Entrib-Main";const char* 密码 = "shopWorx110T";AsyncWebServer 服务器(80);文件根;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'>""<输入类型='文件'名称='更新'>""<输入类型='提交'值='上传'>"</表单>"<div id='prg'>进度:0%</div>"<脚本>""$('form').submit(function(e){"e.preventDefault();""var form = $('#upload_form')[0];""var data = new FormData(form);"" $.ajax({"网址:'/更新',"类型:'POST',"数据:数据,"内容类型:假,"过程数据:假,"xhr:函数(){""var xhr = new window.XMLHttpRequest();""xhr.upload.addEventListener('progress', function(evt){"如果(evt.lengthComputable){"每个变量 = evt.loaded/evt.total;""$('#prg').html('progress:' + Math.round(per*100) + '%');"}"}, 错误的);"返回xhr;""},"成功:功能(d,s){""console.log('成功!')""},"错误:函数(a,b,c){"}""});""});""</脚本>";字符串打印目录(文件目录,int numTabs){字符串响应 = "";dir.rewindDirectory();而(真){文件入口 = dir.openNextFile();如果(!条目){//没有更多文件//Serial.println("**nomorefiles**");休息;}for (uint8_t i=0; isend(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();}空循环(){}

任何人都可以建议对此代码进行任何更改,以使其能够用于从服务器自动下载 SD 卡文件,或者如果您有针对同一问题的任何其他工作代码,我们将不胜感激.谢谢:)

解决方案

我不确定它是否能解决 shalom-daniel 的问题.

我只是想展示我如何从连接到 esp32 的 sd 卡下载名为 data.txt 的文件到客户端.

CS 连接到 Esp32 上的 io 5.

SCK 连接到 Esp32 上的 io 18.

MOSI 连接到 Esp32 上的 io 23.

MISO 连接到 Esp32 上的 io 19.

从 SD.end 开始可能看起来有点奇怪,但这是我让它正常工作的唯一方法.

server.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){SD.end();SD.begin(SD_CS);File file = SD.open("/data.txt");如果(!SD.begin(SD_CS)){Serial.println(挂卡失败");请求->发送(200,text/html",

卡安装失败

");}别的如果(!文件){Serial.println(无法打开文件进行读取");请求->发送(200,text/html",

无法打开文件进行阅读

");}别的{request->send(file, "/data.txt", "text/xhr", true);Serial.print(收到来自客户端IP的data.txt请求");Serial.println(request->client()->remoteIP());}});



#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 :)

解决方案

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

这篇关于如何使服务器使用 arduino for ESP32 WebServer 自动下载文件而不使用 SPIFFS 而是使用 SDcard 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆