added handlers to file server
This commit is contained in:
parent
5ab7c053b9
commit
af7911277d
|
|
@ -3,6 +3,7 @@ idf_component_register(
|
||||||
"src/romfs.c"
|
"src/romfs.c"
|
||||||
"src/spifs.c"
|
"src/spifs.c"
|
||||||
"src/HTTPServer.c"
|
"src/HTTPServer.c"
|
||||||
|
"src/FileServer.c"
|
||||||
"src/HTTPPrintSystem.c"
|
"src/HTTPPrintSystem.c"
|
||||||
"src/HTTPPostSystem.c"
|
"src/HTTPPostSystem.c"
|
||||||
"src/Helpers.c"
|
"src/Helpers.c"
|
||||||
|
|
@ -18,6 +19,8 @@ idf_component_register(
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
"include"
|
"include"
|
||||||
"src"
|
"src"
|
||||||
|
|
||||||
|
EMBED_FILES "upload_script.html"
|
||||||
|
|
||||||
REQUIRES nvs_flash
|
REQUIRES nvs_flash
|
||||||
libespfs
|
libespfs
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,18 @@ typedef enum
|
||||||
HTTP_IO_DONE_NOREFRESH
|
HTTP_IO_DONE_NOREFRESH
|
||||||
} HTTP_IO_RESULT;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
const char tag[16];
|
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);
|
HTTP_IO_RESULT HTTPPostApp(httpd_req_t *req, const char *filename, char *PostData);
|
||||||
int HTTPPrint(httpd_req_t *req, char* buf, char* var);
|
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_ */
|
#endif /* COMPONENTS_WEB_GUI_APPLICATION_INCLUDE_HTTPSERVER_H_ */
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,47 @@
|
||||||
|
|
||||||
#include "HTTPServer.h"
|
#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
|
/* Send HTTP response with a run-time generated html consisting of
|
||||||
* a list of all files and folders under the requested path.
|
* a list of all files and folders under the requested path.
|
||||||
* In case of SPIFFS this returns empty list when path is any
|
* In case of SPIFFS this returns empty list when path is any
|
||||||
* string other than '/', since SPIFFS doesn't support directories */
|
* 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 entrypath[FILE_PATH_MAX];
|
||||||
char entrysize[16];
|
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;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Send HTML file header */
|
/* Send HTML file header */
|
||||||
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
|
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 */
|
/* 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];
|
char filepath[FILE_PATH_MAX];
|
||||||
FILE *fd = NULL;
|
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 */
|
/* Skip leading "/upload" from URI to get filename */
|
||||||
/* Note sizeof() counts NULL termination hence the -1 */
|
/* 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));
|
req->uri + sizeof("/upload") - 1, sizeof(filepath));
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
/* Respond with 500 Internal Server Error */
|
/* 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 */
|
/* 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];
|
char filepath[FILE_PATH_MAX];
|
||||||
struct stat file_stat;
|
struct stat file_stat;
|
||||||
|
|
||||||
/* Skip leading "/delete" from URI to get filename */
|
/* Skip leading "/delete" from URI to get filename */
|
||||||
/* Note sizeof() counts NULL termination hence the -1 */
|
/* 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));
|
req->uri + sizeof("/delete") - 1, sizeof(filepath));
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
/* Respond with 500 Internal Server Error */
|
/* Respond with 500 Internal Server Error */
|
||||||
|
|
|
||||||
|
|
@ -29,16 +29,6 @@ const char GZIP_SIGN[] = { 0x1f, 0x8b, 0x08 };
|
||||||
static esp_err_t GETHandler(httpd_req_t *req);
|
static esp_err_t GETHandler(httpd_req_t *req);
|
||||||
static esp_err_t CheckAuth(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;
|
struct file_server_data *server_data = NULL;
|
||||||
httpd_handle_t server = NULL;
|
httpd_handle_t server = NULL;
|
||||||
static const char *TAG = "HTTPServer";
|
static const char *TAG = "HTTPServer";
|
||||||
|
|
@ -183,6 +173,7 @@ static esp_err_t POSTHandler(httpd_req_t *req)
|
||||||
#if HTTP_SERVER_DEBUG_LEVEL > 0
|
#if HTTP_SERVER_DEBUG_LEVEL > 0
|
||||||
ESP_LOGI(TAG, "POST request handle");
|
ESP_LOGI(TAG, "POST request handle");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *buf = ((struct file_server_data*) req->user_ctx)->scratch;
|
char *buf = ((struct file_server_data*) req->user_ctx)->scratch;
|
||||||
int received;
|
int received;
|
||||||
int remaining = req->content_len;
|
int remaining = req->content_len;
|
||||||
|
|
@ -215,10 +206,20 @@ static esp_err_t POSTHandler(httpd_req_t *req)
|
||||||
if (received)
|
if (received)
|
||||||
{
|
{
|
||||||
char filepath[FILE_PATH_MAX];
|
char filepath[FILE_PATH_MAX];
|
||||||
|
|
||||||
const char *filename = get_path_from_uri(filepath,
|
const char *filename = get_path_from_uri(filepath,
|
||||||
((struct file_server_data*) req->user_ctx)->base_path,
|
((struct file_server_data*) req->user_ctx)->base_path,
|
||||||
req->uri,
|
req->uri,
|
||||||
sizeof(filepath));
|
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))
|
if (!memcmp(filename, "/api", 4))
|
||||||
{
|
{
|
||||||
|
|
@ -295,6 +296,13 @@ static esp_err_t GETHandler(httpd_req_t *req)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!strcmp(filename, "/files.html"))
|
||||||
|
{
|
||||||
|
return http_resp_dir_html(req, "/data");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//check auth for all files except status.json
|
//check auth for all files except status.json
|
||||||
if (strcmp(filename, "/status.json"))
|
if (strcmp(filename, "/status.json"))
|
||||||
{
|
{
|
||||||
|
|
@ -528,6 +536,7 @@ esp_err_t start_file_server(void)
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
strlcpy(server_data->base_path, "/", sizeof("/"));
|
strlcpy(server_data->base_path, "/", sizeof("/"));
|
||||||
|
strlcpy(server_data->base_path2, "/data", sizeof("/data"));
|
||||||
server = start_webserver();
|
server = start_webserver();
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
80
upload_script.html
Normal file
80
upload_script.html
Normal 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>
|
||||||
Loading…
Reference in New Issue
Block a user