Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7d911b9

Browse filesBrowse files
authored
Handle large octet-stream (espressif#9430)
* Handle large octet-stream * Add exemple Upload Huge File * Remove unuse function printDirectory * Fix upload path * Simplify and generalize the body parsing.
1 parent c2a8e25 commit 7d911b9
Copy full SHA for 7d911b9

File tree

7 files changed

+157
-1
lines changed
Filter options

7 files changed

+157
-1
lines changed
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Upload Huge File To SD Over Http
2+
3+
This project is an example of an HTTP server designed to facilitate the transfer of large files using the PUT method, in accordance with RFC specifications.
4+
5+
### Example cURL Command
6+
7+
```bash
8+
curl -X PUT -T ./my-file.mp3 http://esp-ip/upload/my-file.mp3
9+
```
10+
11+
## Resources
12+
13+
- RFC HTTP/1.0 - Additional Request Methods - PUT : [Link](https://datatracker.ietf.org/doc/html/rfc1945#appendix-D.1.1)
+88Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#include <WiFi.h>
2+
#include <WiFiClient.h>
3+
#include <WebServer.h>
4+
#include <uri/UriRegex.h>
5+
#include <SD.h>
6+
7+
const char* ssid = "**********";
8+
const char* password = "**********";
9+
10+
WebServer server(80);
11+
12+
File rawFile;
13+
void handleCreate() {
14+
server.send(200, "text/plain", "");
15+
}
16+
void handleCreateProcess() {
17+
String path = "/" + server.pathArg(0);
18+
HTTPRaw& raw = server.raw();
19+
if (raw.status == RAW_START) {
20+
if (SD.exists((char *)path.c_str())) {
21+
SD.remove((char *)path.c_str());
22+
}
23+
rawFile = SD.open(path.c_str(), FILE_WRITE);
24+
Serial.print("Upload: START, filename: ");
25+
Serial.println(path);
26+
} else if (raw.status == RAW_WRITE) {
27+
if (rawFile) {
28+
rawFile.write(raw.buf, raw.currentSize);
29+
}
30+
Serial.print("Upload: WRITE, Bytes: ");
31+
Serial.println(raw.currentSize);
32+
} else if (raw.status == RAW_END) {
33+
if (rawFile) {
34+
rawFile.close();
35+
}
36+
Serial.print("Upload: END, Size: ");
37+
Serial.println(raw.totalSize);
38+
}
39+
}
40+
41+
void returnFail(String msg) {
42+
server.send(500, "text/plain", msg + "\r\n");
43+
}
44+
45+
void handleNotFound() {
46+
String message = "File Not Found\n\n";
47+
message += "URI: ";
48+
message += server.uri();
49+
message += "\nMethod: ";
50+
message += (server.method() == HTTP_GET) ? "GET" : "POST";
51+
message += "\nArguments: ";
52+
message += server.args();
53+
message += "\n";
54+
for (uint8_t i = 0; i < server.args(); i++) {
55+
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
56+
}
57+
server.send(404, "text/plain", message);
58+
}
59+
60+
void setup(void) {
61+
Serial.begin(115200);
62+
63+
while (!SD.begin()) delay(1);
64+
Serial.println("SD Card initialized.");
65+
66+
WiFi.mode(WIFI_STA);
67+
WiFi.begin(ssid, password);
68+
69+
while (WiFi.status() != WL_CONNECTED) {
70+
delay(500);
71+
Serial.print(".");
72+
}
73+
Serial.print("Connected to ");
74+
Serial.println(ssid);
75+
Serial.print("IP address: ");
76+
Serial.println(WiFi.localIP());
77+
78+
server.on(UriRegex("/upload/(.*)"), HTTP_PUT, handleCreate, handleCreateProcess);
79+
server.onNotFound(handleNotFound);
80+
server.begin();
81+
Serial.println("HTTP server started");
82+
83+
}
84+
85+
void loop(void) {
86+
server.handleClient();
87+
delay(2);//allow the cpu to switch to other tasks
88+
}

‎libraries/WebServer/src/Parsing.cpp

Copy file name to clipboardExpand all lines: libraries/WebServer/src/Parsing.cpp
+24-1Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,30 @@ bool WebServer::_parseRequest(WiFiClient& client) {
173173
}
174174
}
175175

176-
if (!isForm){
176+
if (!isForm && _currentHandler && _currentHandler->canRaw(_currentUri)){
177+
log_v("Parse raw");
178+
_currentRaw.reset(new HTTPRaw());
179+
_currentRaw->status = RAW_START;
180+
_currentRaw->totalSize = 0;
181+
_currentRaw->currentSize = 0;
182+
log_v("Start Raw");
183+
_currentHandler->raw(*this, _currentUri, *_currentRaw);
184+
_currentRaw->status = RAW_WRITE;
185+
186+
while (_currentRaw->totalSize < _clientContentLength) {
187+
_currentRaw->currentSize = client.readBytes(_currentRaw->buf, HTTP_RAW_BUFLEN);
188+
_currentRaw->totalSize += _currentRaw->currentSize;
189+
if (_currentRaw->currentSize == 0) {
190+
_currentRaw->status = RAW_ABORTED;
191+
_currentHandler->raw(*this, _currentUri, *_currentRaw);
192+
return false;
193+
}
194+
_currentHandler->raw(*this, _currentUri, *_currentRaw);
195+
}
196+
_currentRaw->status = RAW_END;
197+
_currentHandler->raw(*this, _currentUri, *_currentRaw);
198+
log_v("Finish Raw");
199+
} else if (!isForm) {
177200
size_t plainLength;
178201
char* plainBuf = readBytesWithTimeout(client, _clientContentLength, plainLength, HTTP_MAX_POST_WAIT);
179202
if (plainLength < _clientContentLength) {

‎libraries/WebServer/src/WebServer.cpp

Copy file name to clipboardExpand all lines: libraries/WebServer/src/WebServer.cpp
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ void WebServer::handleClient() {
333333
_currentClient = WiFiClient();
334334
_currentStatus = HC_NONE;
335335
_currentUpload.reset();
336+
_currentRaw.reset();
336337
}
337338

338339
if (callYield) {

‎libraries/WebServer/src/WebServer.h

Copy file name to clipboardExpand all lines: libraries/WebServer/src/WebServer.h
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END,
3434
UPLOAD_FILE_ABORTED };
35+
enum HTTPRawStatus { RAW_START, RAW_WRITE, RAW_END, RAW_ABORTED };
3536
enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE };
3637
enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
3738

@@ -41,6 +42,10 @@ enum HTTPAuthMethod { BASIC_AUTH, DIGEST_AUTH };
4142
#define HTTP_UPLOAD_BUFLEN 1436
4243
#endif
4344

45+
#ifndef HTTP_RAW_BUFLEN
46+
#define HTTP_RAW_BUFLEN 1436
47+
#endif
48+
4449
#define HTTP_MAX_DATA_WAIT 5000 //ms to wait for the client to send the request
4550
#define HTTP_MAX_POST_WAIT 5000 //ms to wait for POST data to arrive
4651
#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed
@@ -61,6 +66,15 @@ typedef struct {
6166
uint8_t buf[HTTP_UPLOAD_BUFLEN];
6267
} HTTPUpload;
6368

69+
typedef struct
70+
{
71+
HTTPRawStatus status;
72+
size_t totalSize; // content size
73+
size_t currentSize; // size of data currently in buf
74+
uint8_t buf[HTTP_UPLOAD_BUFLEN];
75+
void *data; // additional data
76+
} HTTPRaw;
77+
6478
#include "detail/RequestHandler.h"
6579

6680
namespace fs {
@@ -97,6 +111,7 @@ class WebServer
97111
HTTPMethod method() { return _currentMethod; }
98112
virtual WiFiClient client() { return _currentClient; }
99113
HTTPUpload& upload() { return *_currentUpload; }
114+
HTTPRaw& raw() { return *_currentRaw; }
100115

101116
String pathArg(unsigned int i); // get request path argument by number
102117
String arg(String name); // get request argument value by name
@@ -196,6 +211,7 @@ class WebServer
196211
RequestArgument* _postArgs;
197212

198213
std::unique_ptr<HTTPUpload> _currentUpload;
214+
std::unique_ptr<HTTPRaw> _currentRaw;
199215

200216
int _headerKeysCount;
201217
RequestArgument* _currentHeaders;

‎libraries/WebServer/src/detail/RequestHandler.h

Copy file name to clipboardExpand all lines: libraries/WebServer/src/detail/RequestHandler.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ class RequestHandler {
99
virtual ~RequestHandler() { }
1010
virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; }
1111
virtual bool canUpload(String uri) { (void) uri; return false; }
12+
virtual bool canRaw(String uri) { (void) uri; return false; }
1213
virtual bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) { (void) server; (void) requestMethod; (void) requestUri; return false; }
1314
virtual void upload(WebServer& server, String requestUri, HTTPUpload& upload) { (void) server; (void) requestUri; (void) upload; }
15+
virtual void raw(WebServer& server, String requestUri, HTTPRaw& raw) { (void) server; (void) requestUri; (void) raw; }
1416

1517
RequestHandler* next() { return _next; }
1618
void next(RequestHandler* r) { _next = r; }

‎libraries/WebServer/src/detail/RequestHandlersImpl.h

Copy file name to clipboardExpand all lines: libraries/WebServer/src/detail/RequestHandlersImpl.h
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ class FunctionRequestHandler : public RequestHandler {
3636

3737
return true;
3838
}
39+
bool canRaw(String requestUri) override {
40+
if (!_ufn || _method == HTTP_GET)
41+
return false;
42+
43+
return true;
44+
}
3945

4046
bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) override {
4147
(void) server;
@@ -53,6 +59,13 @@ class FunctionRequestHandler : public RequestHandler {
5359
_ufn();
5460
}
5561

62+
void raw(WebServer& server, String requestUri, HTTPRaw& raw) override {
63+
(void)server;
64+
(void)raw;
65+
if (canRaw(requestUri))
66+
_ufn();
67+
}
68+
5669
protected:
5770
WebServer::THandlerFunction _fn;
5871
WebServer::THandlerFunction _ufn;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.