summaryrefslogtreecommitdiff
path: root/libraries/ESP_Async_WebServer/examples/Upload/Upload.ino
blob: ceac47ddda601678ad0035545e1aa3e8b66de9fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// 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);
}