if you use ESPAsyncWebServer it's pretty simple
try this
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "xxxxxxxx";
const char* password = "xxxxxxxx";
AsyncWebServer server(80);
// Embedded HTML code as a raw string literal
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<h2>Upload a file</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="fileToUpload" id="fileToUpload">
<input type="submit" value="Upload File" name="submit">
</form>
</body>
</html>
)rawliteral";
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
while (true) yield();
}
Serial.println("Connected to WiFi");
Serial.print("Open URL http://"); Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
request->send_P(200, "text/html", index_html);
});
server.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
request->send(200);
}, [](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if (!index) {
Serial.print("Receiving file: ");
Serial.println(filename);
}
for(size_t i = 0; i < len; i++){
Serial.write(data[i]);
}
if(final) {
Serial.println("\n-----------\nFile upload completed");
}
});
server.begin();
}
void loop() {}
change the xxxxxx to match your wireless network details
compile and upload to your ESP32, open the Serial monitor at 115200 bauds
You'll see something like
Connected to WiFi
Open URL http://10.116.1.22
Connect to the url printed in the serial monitor (here http://10.116.1.22)
you'll see a simple web interface (localised, my system runs in French)

click on the button to select a file from your file selector in the web browser
the file name will show next to the button
click the
button
you'll see in the serial monitor the bytes coming in.
the callback method is using chunks so if you want to save the file in RAM on the ESP32 you'll have to do that in the lambda function which will be called a number of time (until the final flag is set)