我想使用 ESPAsyncWebServer 库在 ESP32 上运行一个简单的 Web 服务器。在网页上,您应该能够选择要上传到 SD 卡的文件。您还应该能够从下拉菜单中选择将文件上传到三个目录中的哪一个。文件已上传,但仅上传至根目录,未上传至相应文件夹。变量“目录”始终为空。显然该请求无法正常工作。我究竟做错了什么?感谢您的帮助!
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <SD.h>
#include <SPIFFS.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const char* ssid = "myWifi";
const char* password = "myPassword";
AsyncWebServer server(80);
void setup() {
Serial.begin(115200);
if (!SD.begin()) {
Serial.println("Failed to mount SD card.");
return;
}
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", getWebpage());
});
server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
request->send(200);
}, handleUpload);
server.begin();
}
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
static File file;
static String path;
if (!index) {
String directory = request->arg("selektor");
path = "/" + directory + "/" + filename;
file = SD.open(path, FILE_WRITE);
Serial.println("Verzeichnis: " + path);
}
if (file) {
for (size_t i = 0; i < len; i++) {
file.write(data[i]);
}
if (final) {
file.close();
display.clearDisplay();
display.setCursor(0,0);
display.println("Datei hochgeladen:");
display.println(filename);
display.display();
}
}
}
void loop() {
}
String getWebpage() {
String page = "<!DOCTYPE html><html><head><title>ESP32 Option Selector</title></head><body>";
page += "<form method='POST' action='/upload' enctype='multipart/form-data'><input type='file' name='upload'><br><select name='selektor'>";
page += "<form action='/submit' method='post'>";
page += "<option value='dir1'>Directory 1</option>";
page += "<option value='dir2'>Directory 2</option>";
page += "<option value='dir3'>Directory 3</option>";
page += "</select><input type='submit' value='Upload'></form></body></html>";
return page;
}
ESP32AsyncWebServer POST 请求的 API 有 3 个回调函数:
server.on("/uri", HTTP_POST, onRequest, onFileUpload, onBody);
针对不同的应用场景,每个回调都有不同的参数。
使用哪个回调函数取决于 POST 请求的类型以及从客户端发送到服务器的数据的组合。如果仅包含 post 请求有效负载(例如序列化的 json 对象),则使用
onBody()
;当您请求仅包含要上传的文件(其中已提供文件名和文件数据、长度)时,使用 onFileUpload()
回调作为回调函数的参数。对于 multipart
负载,它可以包含文件和进一步的请求正文,您需要使用 onRequest()
回调,onRequest()
函数参数仅包含 request
对象,但您可以获得所有类型通过调用相关请求方法获取您需要的数据。
因此,对于您的情况,您将需要使用
onRequest()
回调。
void onRequest(AsyncWebServerRequest *request) {
if (request->hasArg("upload") && request->hasArg("selektor")) {
String path = "/" + request->arg("selektor") + "/" + request->arg("upload");
Serial.printf("path %s\n", path.c_str());
request->send(200, "text/plain", "Ok");
}
else {
request->send(400, "text/plain", "Bad request");
}
}
void setup() {
// other setup codes omitted here
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", getWebpage());
});
server.on("/upload", HTTP_POST, onRequest);
server.begin();
}