added handlers to file server

This commit is contained in:
Bogdan Pilyugin 2022-11-15 13:49:27 +02:00
parent 5ab7c053b9
commit af7911277d
5 changed files with 161 additions and 16 deletions

View File

@ -3,6 +3,7 @@ idf_component_register(
"src/romfs.c"
"src/spifs.c"
"src/HTTPServer.c"
"src/FileServer.c"
"src/HTTPPrintSystem.c"
"src/HTTPPostSystem.c"
"src/Helpers.c"
@ -18,6 +19,8 @@ idf_component_register(
INCLUDE_DIRS "."
"include"
"src"
EMBED_FILES "upload_script.html"
REQUIRES nvs_flash
libespfs

View File

@ -67,6 +67,18 @@ typedef enum
HTTP_IO_DONE_NOREFRESH
} HTTP_IO_RESULT;
struct file_server_data
{
/* Base path of file storage */
char base_path[ESP_VFS_PATH_MAX + 1];
char base_path2[ESP_VFS_PATH_MAX + 1];
/* Scratch buffer for temporary storage during file transfer */
char scratch[SCRATCH_BUFSIZE];
/* Pointer to external POST handler*/
};
typedef struct
{
const char tag[16];
@ -81,4 +93,9 @@ esp_err_t start_file_server(void);
HTTP_IO_RESULT HTTPPostApp(httpd_req_t *req, const char *filename, char *PostData);
int HTTPPrint(httpd_req_t *req, char* buf, char* var);
esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath);
esp_err_t upload_post_handler(httpd_req_t *req);
esp_err_t delete_post_handler(httpd_req_t *req);
#endif /* COMPONENTS_WEB_GUI_APPLICATION_INCLUDE_HTTPSERVER_H_ */

View File

@ -24,13 +24,47 @@
#include "HTTPServer.h"
static const char *TAG = "HTTPServer";
static const char *TAG = "FileServer";
/* Copies the full path into destination buffer and returns
* pointer to path (skipping the preceding base path) */
static const char* get_path_from_uri(char *dest, const char *base_path,
const char *uri,
size_t destsize)
{
const size_t base_pathlen = strlen(base_path);
size_t pathlen = strlen(uri);
const char *quest = strchr(uri, '?');
if (quest)
{
pathlen = MIN(pathlen, quest - uri);
}
const char *hash = strchr(uri, '#');
if (hash)
{
pathlen = MIN(pathlen, hash - uri);
}
if (base_pathlen + pathlen + 1 > destsize)
{
/* Full path string won't fit into destination buffer */
return NULL;
}
/* Construct full path (base + path) */
strcpy(dest, base_path);
strlcpy(dest + base_pathlen, uri, pathlen + 1);
/* Return pointer to path, skipping the base */
return dest + base_pathlen;
}
/* Send HTTP response with a run-time generated html consisting of
* a list of all files and folders under the requested path.
* In case of SPIFFS this returns empty list when path is any
* string other than '/', since SPIFFS doesn't support directories */
static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
{
char entrypath[FILE_PATH_MAX];
char entrysize[16];
@ -52,6 +86,8 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
return ESP_FAIL;
}
/* Send HTML file header */
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
@ -116,7 +152,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath)
}
/* Handler to upload a file onto the server */
static esp_err_t upload_post_handler(httpd_req_t *req)
esp_err_t upload_post_handler(httpd_req_t *req)
{
char filepath[FILE_PATH_MAX];
FILE *fd = NULL;
@ -124,7 +160,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
/* Skip leading "/upload" from URI to get filename */
/* Note sizeof() counts NULL termination hence the -1 */
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path2,
req->uri + sizeof("/upload") - 1, sizeof(filepath));
if (!filename) {
/* Respond with 500 Internal Server Error */
@ -230,14 +266,14 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
}
/* Handler to delete a file from the server */
static esp_err_t delete_post_handler(httpd_req_t *req)
esp_err_t delete_post_handler(httpd_req_t *req)
{
char filepath[FILE_PATH_MAX];
struct stat file_stat;
/* Skip leading "/delete" from URI to get filename */
/* Note sizeof() counts NULL termination hence the -1 */
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path2,
req->uri + sizeof("/delete") - 1, sizeof(filepath));
if (!filename) {
/* Respond with 500 Internal Server Error */

View File

@ -29,16 +29,6 @@ const char GZIP_SIGN[] = { 0x1f, 0x8b, 0x08 };
static esp_err_t GETHandler(httpd_req_t *req);
static esp_err_t CheckAuth(httpd_req_t *req);
struct file_server_data
{
/* Base path of file storage */
char base_path[ESP_VFS_PATH_MAX + 1];
/* Scratch buffer for temporary storage during file transfer */
char scratch[SCRATCH_BUFSIZE];
/* Pointer to external POST handler*/
};
struct file_server_data *server_data = NULL;
httpd_handle_t server = NULL;
static const char *TAG = "HTTPServer";
@ -183,6 +173,7 @@ static esp_err_t POSTHandler(httpd_req_t *req)
#if HTTP_SERVER_DEBUG_LEVEL > 0
ESP_LOGI(TAG, "POST request handle");
#endif
char *buf = ((struct file_server_data*) req->user_ctx)->scratch;
int received;
int remaining = req->content_len;
@ -215,10 +206,20 @@ static esp_err_t POSTHandler(httpd_req_t *req)
if (received)
{
char filepath[FILE_PATH_MAX];
const char *filename = get_path_from_uri(filepath,
((struct file_server_data*) req->user_ctx)->base_path,
req->uri,
sizeof(filepath));
ESP_LOGW(TAG, "filepath %s", filepath);
filename = get_path_from_uri(filepath,
((struct file_server_data*) req->user_ctx)->base_path,
req->uri,
sizeof(filepath));
if (!memcmp(filename, "/api", 4))
{
@ -295,6 +296,13 @@ static esp_err_t GETHandler(httpd_req_t *req)
return ESP_OK;
}
if (!strcmp(filename, "/files.html"))
{
return http_resp_dir_html(req, "/data");
}
//check auth for all files except status.json
if (strcmp(filename, "/status.json"))
{
@ -528,6 +536,7 @@ esp_err_t start_file_server(void)
return ESP_ERR_NO_MEM;
}
strlcpy(server_data->base_path, "/", sizeof("/"));
strlcpy(server_data->base_path2, "/data", sizeof("/data"));
server = start_webserver();
return ESP_OK;
}

80
upload_script.html Normal file
View File

@ -0,0 +1,80 @@
<table class="fixed" border="0">
<col width="1000px" /><col width="500px" />
<tr><td>
<h2>ESP32 File Server</h2>
</td><td>
<table border="0">
<tr>
<td>
<label for="newfile">Upload a file</label>
</td>
<td colspan="2">
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
</td>
</tr>
<tr>
<td>
<label for="filepath">Set path on server</label>
</td>
<td>
<input id="filepath" type="text" style="width:100%;">
</td>
<td>
<button id="upload" type="button" onclick="upload()">Upload</button>
</td>
</tr>
</table>
</td></tr>
</table>
<script>
function setpath() {
var default_path = document.getElementById("newfile").files[0].name;
document.getElementById("filepath").value = default_path;
}
function upload() {
var filePath = document.getElementById("filepath").value;
var upload_path = "/upload/" + filePath;
var fileInput = document.getElementById("newfile").files;
/* Max size of an individual file. Make sure this
* value is same as that set in file_server.c */
var MAX_FILE_SIZE = 200*1024;
var MAX_FILE_SIZE_STR = "200KB";
if (fileInput.length == 0) {
alert("No file selected!");
} else if (filePath.length == 0) {
alert("File path on server is not set!");
} else if (filePath.indexOf(' ') >= 0) {
alert("File path on server cannot have spaces!");
} else if (filePath[filePath.length-1] == '/') {
alert("File name not specified after path!");
} else if (fileInput[0].size > 200*1024) {
alert("File size must be less than 200KB!");
} else {
document.getElementById("newfile").disabled = true;
document.getElementById("filepath").disabled = true;
document.getElementById("upload").disabled = true;
var file = fileInput[0];
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.open();
document.write(xhttp.responseText);
document.close();
} else if (xhttp.status == 0) {
alert("Server closed the connection abruptly!");
location.reload()
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
location.reload()
}
}
};
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
</script>