172 lines
4.7 KiB
C++
172 lines
4.7 KiB
C++
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
|
|
|
|
//
|
|
// Demo text, binary and file upload
|
|
//
|
|
|
|
#include <Arduino.h>
|
|
#ifdef ESP32
|
|
#include <AsyncTCP.h>
|
|
#include <WiFi.h>
|
|
#elif defined(ESP8266)
|
|
#include <ESP8266WiFi.h>
|
|
#include <ESPAsyncTCP.h>
|
|
#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350)
|
|
#include <RPAsyncTCP.h>
|
|
#include <WiFi.h>
|
|
#endif
|
|
|
|
#include <ESPAsyncWebServer.h>
|
|
#include <StreamString.h>
|
|
#include <LittleFS.h>
|
|
|
|
static AsyncWebServer server(80);
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
|
|
if (!LittleFS.begin()) {
|
|
LittleFS.format();
|
|
LittleFS.begin();
|
|
}
|
|
|
|
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
|
WiFi.mode(WIFI_AP);
|
|
WiFi.softAP("esp-captive");
|
|
#endif
|
|
|
|
// 1. Generate a Lorem_ipsum.txt file of about 20KB of text
|
|
//
|
|
// 3. Run: curl -v -F "data=@Lorem_ipsum.txt" http://192.168.4.1/upload/text
|
|
//
|
|
server.on(
|
|
"/upload/text", HTTP_POST,
|
|
[](AsyncWebServerRequest *request) {
|
|
if (!request->_tempObject) {
|
|
return request->send(400, "text/plain", "Nothing uploaded");
|
|
}
|
|
StreamString *buffer = reinterpret_cast<StreamString *>(request->_tempObject);
|
|
Serial.printf("Text uploaded:\n%s\n", buffer->c_str());
|
|
delete buffer;
|
|
request->_tempObject = nullptr;
|
|
request->send(200, "text/plain", "OK");
|
|
},
|
|
[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
|
Serial.printf("Upload[%s]: start=%u, len=%u, final=%d\n", filename.c_str(), index, len, final);
|
|
|
|
if (!index) {
|
|
// first pass
|
|
StreamString *buffer = new StreamString();
|
|
size_t size = std::max(4094l, request->header("Content-Length").toInt());
|
|
Serial.printf("Allocating string buffer of %u bytes\n", size);
|
|
if (!buffer->reserve(size)) {
|
|
delete buffer;
|
|
request->abort();
|
|
}
|
|
request->_tempObject = buffer;
|
|
}
|
|
|
|
if (len) {
|
|
reinterpret_cast<StreamString *>(request->_tempObject)->write(data, len);
|
|
}
|
|
}
|
|
);
|
|
|
|
// 1. Generate a Lorem_ipsum.txt file of about 20KB of text
|
|
//
|
|
// 3. Run: curl -v -F "data=@Lorem_ipsum.txt" http://192.168.4.1/upload/file
|
|
//
|
|
server.on(
|
|
"/upload/file", HTTP_POST,
|
|
[](AsyncWebServerRequest *request) {
|
|
if (request->getResponse()) {
|
|
// 400 File not available for writing
|
|
return;
|
|
}
|
|
|
|
if (!LittleFS.exists("/my_file.txt")) {
|
|
return request->send(400, "text/plain", "Nothing uploaded");
|
|
}
|
|
|
|
// sends back the uploaded file
|
|
request->send(LittleFS, "/my_file.txt", "text/plain");
|
|
},
|
|
[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
|
Serial.printf("Upload[%s]: start=%u, len=%u, final=%d\n", filename.c_str(), index, len, final);
|
|
|
|
if (!index) {
|
|
request->_tempFile = LittleFS.open("/my_file.txt", "w");
|
|
|
|
if (!request->_tempFile) {
|
|
request->send(400, "text/plain", "File not available for writing");
|
|
}
|
|
}
|
|
if (len) {
|
|
request->_tempFile.write(data, len);
|
|
}
|
|
if (final) {
|
|
request->_tempFile.close();
|
|
}
|
|
}
|
|
);
|
|
|
|
//
|
|
// Upload a binary file: curl -v -F "data=@file.mp3" http://192.168.4.1/upload/binary
|
|
//
|
|
server.on(
|
|
"/upload/binary", HTTP_POST,
|
|
[](AsyncWebServerRequest *request) {
|
|
// response already set ?
|
|
if (request->getResponse()) {
|
|
// 400 No Content-Length
|
|
return;
|
|
}
|
|
|
|
// nothing uploaded ?
|
|
if (!request->_tempObject) {
|
|
return request->send(400, "text/plain", "Nothing uploaded");
|
|
}
|
|
|
|
uint8_t *buffer = reinterpret_cast<uint8_t *>(request->_tempObject);
|
|
// process the buffer
|
|
|
|
delete buffer;
|
|
request->_tempObject = nullptr;
|
|
|
|
request->send(200, "text/plain", "OK");
|
|
},
|
|
[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
|
Serial.printf("Upload[%s]: start=%u, len=%u, final=%d\n", filename.c_str(), index, len, final);
|
|
|
|
// first pass ?
|
|
if (!index) {
|
|
size_t size = request->header("Content-Length").toInt();
|
|
if (!size) {
|
|
request->send(400, "text/plain", "No Content-Length");
|
|
} else {
|
|
Serial.printf("Allocating buffer of %u bytes\n", size);
|
|
uint8_t *buffer = new (std::nothrow) uint8_t[size];
|
|
if (!buffer) {
|
|
// not enough memory
|
|
request->abort();
|
|
} else {
|
|
request->_tempObject = buffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (len) {
|
|
memcpy(reinterpret_cast<uint8_t *>(request->_tempObject) + index, data, len);
|
|
}
|
|
}
|
|
);
|
|
|
|
server.begin();
|
|
}
|
|
|
|
// not needed
|
|
void loop() {
|
|
delay(100);
|
|
}
|