diff --git a/docs/README.md b/docs/README.md index 0029e0cf..907833f4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1319,6 +1319,54 @@ A diagram below shows how `mg_http_next_multipart()` in action: Function mg_http_next_multipart() +### mg\_http\_upload() + +```c + +int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, + struct mg_fs *fs, const char *dir); +``` + +This is a helper utility function that is used to upload large files by small +chunks. + +Append HTTP POST data to a file in a specified directory. A file name and +file offset are specified by the query string parameters: +`POST /upload?name=firmware.bin&offset=2048 HTTP/1.1`. If the offset is 0, then the +file is truncated. It is a client's responsibility to divide a file into a +smaller chunks and send a sequence of POST requests that will be handled by +this function. + +Parameters: +- `c`- a connection +- `hm` - a parsed HTTP message +- `fs` - a filesystem where to write a file, e.g. `&mg_fs_posix` +- `dir` - a directory name where a file should be stored + +Return value: number of bytes written + +Usage example: + +```c +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { + if (ev == MG_EV_HTTP_MSG) { + struct mg_http_message *hm = (struct mg_http_message *) ev_data; + if (mg_http_match_uri(hm, "/upload")) { + mg_http_upload(c, hm, &mg_fs_posix, "/tmp"); + } else { + struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve + mg_http_serve_dir(c, ev_data, &opts); // static content + } + } +} + +``` + +See [app.js](https://github.com/cesanta/mongoose/blob/7.5/examples/file-upload/web_root/app.js) +for the example Javascript HTML page code that takes a file and +sends it by small chunks. + + ## Websocket ### struct mg\_ws\_message diff --git a/mongoose.c b/mongoose.c index 3dbfb1a0..a6a76684 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1859,7 +1859,9 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, if (name[0] == '\0') { mg_http_reply(c, 400, "", "%s", "name required"); res = -1; - } else if (hm->body.len > 0) { + } else if (hm->body.len == 0) { + mg_http_reply(c, 200, "", "%d", res); // Nothing to write + } else { struct mg_fd *fd; long oft = strtol(offset, NULL, 0); mg_snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name); diff --git a/src/http.c b/src/http.c index 8ee5dd8a..4284dc5c 100644 --- a/src/http.c +++ b/src/http.c @@ -865,7 +865,9 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm, if (name[0] == '\0') { mg_http_reply(c, 400, "", "%s", "name required"); res = -1; - } else if (hm->body.len > 0) { + } else if (hm->body.len == 0) { + mg_http_reply(c, 200, "", "%d", res); // Nothing to write + } else { struct mg_fd *fd; long oft = strtol(offset, NULL, 0); mg_snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, name);