From 4c078799caf1454af8c7e58702d1be033644ce6d Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Wed, 21 Oct 2015 14:09:55 +0300 Subject: [PATCH] Add SPIFFS WebServer Example --- .../examples/FSBrowser/FSBrowser.ino | 239 ++++++++++++++++++ .../examples/FSBrowser/data/edit.htm.gz | Bin 0 -> 4116 bytes .../examples/FSBrowser/data/favicon.ico | Bin 0 -> 1150 bytes .../examples/FSBrowser/data/graphs.js.gz | Bin 0 -> 1971 bytes .../examples/FSBrowser/data/index.htm | 97 +++++++ 5 files changed, 336 insertions(+) create mode 100644 libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino create mode 100644 libraries/ESP8266WebServer/examples/FSBrowser/data/edit.htm.gz create mode 100644 libraries/ESP8266WebServer/examples/FSBrowser/data/favicon.ico create mode 100644 libraries/ESP8266WebServer/examples/FSBrowser/data/graphs.js.gz create mode 100644 libraries/ESP8266WebServer/examples/FSBrowser/data/index.htm diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino new file mode 100644 index 000000000..f8b43e34d --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino @@ -0,0 +1,239 @@ +/* + FSWebServer - Example WebServer with SPIFFS backend for esp8266 + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the ESP8266WebServer library for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) + or you can upload the contents of a folder if you CD in that folder and run the following command: + for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done + + access the sample web page at http://esp8266fs.local + edit the page by going to http://esp8266fs.local/edit +*/ +#include +#include +#include +#include +#include + +#define DBG_OUTPUT_PORT Serial + +const char* ssid = "wifi-ssid"; +const char* password = "wifi-password"; +const char* host = "esp8266fs"; + +ESP8266WebServer server(80); +//holds the current upload +File fsUploadFile; + +//format bytes +String formatBytes(size_t bytes){ + if (bytes < 1024){ + return String(bytes)+"B"; + } else if(bytes < (1024 * 1024)){ + return String(bytes/1024.0)+"KB"; + } else if(bytes < (1024 * 1024 * 1024)){ + return String(bytes/1024.0/1024.0)+"MB"; + } else { + return String(bytes/1024.0/1024.0/1024.0)+"GB"; + } +} + +String getContentType(String filename){ + if(server.hasArg("download")) return "application/octet-stream"; + else if(filename.endsWith(".htm")) return "text/html"; + else if(filename.endsWith(".html")) return "text/html"; + else if(filename.endsWith(".css")) return "text/css"; + else if(filename.endsWith(".js")) return "application/javascript"; + else if(filename.endsWith(".png")) return "image/png"; + else if(filename.endsWith(".gif")) return "image/gif"; + else if(filename.endsWith(".jpg")) return "image/jpeg"; + else if(filename.endsWith(".ico")) return "image/x-icon"; + else if(filename.endsWith(".xml")) return "text/xml"; + else if(filename.endsWith(".pdf")) return "application/x-pdf"; + else if(filename.endsWith(".zip")) return "application/x-zip"; + else if(filename.endsWith(".gz")) return "application/x-gzip"; + return "text/plain"; +} + +bool handleFileRead(String path){ + DBG_OUTPUT_PORT.println("handleFileRead: " + path); + if(path.endsWith("/")) path += "index.htm"; + String contentType = getContentType(path); + String pathWithGz = path + ".gz"; + if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){ + if(SPIFFS.exists(pathWithGz)) + path += ".gz"; + File file = SPIFFS.open(path, "r"); + size_t sent = server.streamFile(file, contentType); + file.close(); + return true; + } + return false; +} + +void handleFileUpload(){ + if(server.uri() != "/edit") return; + HTTPUpload& upload = server.upload(); + if(upload.status == UPLOAD_FILE_START){ + String filename = upload.filename; + if(!filename.startsWith("/")) filename = "/"+filename; + DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename); + fsUploadFile = SPIFFS.open(filename, "w"); + filename = String(); + } else if(upload.status == UPLOAD_FILE_WRITE){ + //DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize); + if(fsUploadFile) + fsUploadFile.write(upload.buf, upload.currentSize); + } else if(upload.status == UPLOAD_FILE_END){ + if(fsUploadFile) + fsUploadFile.close(); + DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize); + } +} + +void handleFileDelete(){ + if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS"); + String path = server.arg(0); + DBG_OUTPUT_PORT.println("handleFileDelete: " + path); + if(path == "/") + return server.send(500, "text/plain", "BAD PATH"); + if(!SPIFFS.exists(path)) + return server.send(404, "text/plain", "FileNotFound"); + SPIFFS.remove(path); + server.send(200, "text/plain", ""); + path = String(); +} + +void handleFileCreate(){ + if(server.args() == 0) + return server.send(500, "text/plain", "BAD ARGS"); + String path = server.arg(0); + DBG_OUTPUT_PORT.println("handleFileCreate: " + path); + if(path == "/") + return server.send(500, "text/plain", "BAD PATH"); + if(SPIFFS.exists(path)) + return server.send(500, "text/plain", "FILE EXISTS"); + File file = SPIFFS.open(path, "w"); + if(file) + file.close(); + else + return server.send(500, "text/plain", "CREATE FAILED"); + server.send(200, "text/plain", ""); + path = String(); +} + +void handleFileList() { + if(!server.hasArg("dir")) {server.send(500, "text/plain", "BAD ARGS"); return;} + + String path = server.arg("dir"); + DBG_OUTPUT_PORT.println("handleFileList: " + path); + Dir dir = SPIFFS.openDir(path); + path = String(); + + String output = "["; + while(dir.next()){ + File entry = dir.openFile("r"); + if (output != "[") output += ','; + bool isDir = false; + output += "{\"type\":\""; + output += (isDir)?"dir":"file"; + output += "\",\"name\":\""; + output += String(entry.name()).substring(1); + output += "\"}"; + entry.close(); + } + + output += "]"; + server.send(200, "text/json", output); +} + +void setup(void){ + DBG_OUTPUT_PORT.begin(115200); + DBG_OUTPUT_PORT.print("\n"); + DBG_OUTPUT_PORT.setDebugOutput(true); + SPIFFS.begin(); + { + Dir dir = SPIFFS.openDir("/"); + while (dir.next()) { + String fileName = dir.fileName(); + size_t fileSize = dir.fileSize(); + DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str()); + } + DBG_OUTPUT_PORT.printf("\n"); + } + + + //WIFI INIT + DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid); + if (String(WiFi.SSID()) != String(ssid)) { + WiFi.begin(ssid, password); + } + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + DBG_OUTPUT_PORT.print("."); + } + DBG_OUTPUT_PORT.println(""); + DBG_OUTPUT_PORT.print("Connected! IP address: "); + DBG_OUTPUT_PORT.println(WiFi.localIP()); + + MDNS.begin(host); + DBG_OUTPUT_PORT.print("Open http://"); + DBG_OUTPUT_PORT.print(host); + DBG_OUTPUT_PORT.println(".local/edit to see the file browser"); + + + //SERVER INIT + //list directory + server.on("/list", HTTP_GET, handleFileList); + //load editor + server.on("/edit", HTTP_GET, [](){ + if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound"); + }); + //create file + server.on("/edit", HTTP_PUT, handleFileCreate); + //delete file + server.on("/edit", HTTP_DELETE, handleFileDelete); + //called after file upload + server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }); + //called when a file is received inside POST data + server.onFileUpload(handleFileUpload); + + //called when the url is not defined here + //use it to load content from SPIFFS + server.onNotFound([](){ + if(!handleFileRead(server.uri())) + server.send(404, "text/plain", "FileNotFound"); + }); + + //get heap status, analog input value and all GPIO statuses in one json call + server.on("/all", HTTP_GET, [](){ + String json = "{"; + json += "\"heap\":"+String(ESP.getFreeHeap()); + json += ", \"analog\":"+String(analogRead(A0)); + json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); + json += "}"; + server.send(200, "text/json", json); + json = String(); + }); + server.begin(); + DBG_OUTPUT_PORT.println("HTTP server started"); + +} + +void loop(void){ + server.handleClient(); +} diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/data/edit.htm.gz b/libraries/ESP8266WebServer/examples/FSBrowser/data/edit.htm.gz new file mode 100644 index 0000000000000000000000000000000000000000..69ce414f47f4b25a70160fc4985b2bd320c9b90a GIT binary patch literal 4116 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 literal 0 HcmV?d00001 diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/data/graphs.js.gz b/libraries/ESP8266WebServer/examples/FSBrowser/data/graphs.js.gz new file mode 100644 index 0000000000000000000000000000000000000000..72435445a7ef86e00fe6c66b3b71c47fdbd53a93 GIT binary patch literal 1971 zcmV;k2Tb@MiwFo@s$5k717~t!aAw-*8%!ep`yEM!aI@XpTRzN;M>CH`Bk93rb1y+*nfgVXr6{*O z+qWk+vpIfdbmRB&GiOD~!8-BI8jWLya*xm0`?Ns*u7@$U5b~-2FAtyY?VsHiJWiul z$g}Ci$m17Tz>sgbNBG!p6`3AIdmW5d-8e)$jYf;JJn?*ncK^L=>v4>q7o#|V#AXxo zd(ilSPVW5&A*9`%(ECk!Y+arKfe)*P?pEpRp~jzoF096?>r=Aoz97T=5)|h&-xQIu zg>l28ew8E08a6CBp`}c_5jC)_GP?DY`3f}-jd!TP&)0@aTI6>ySBJ(C^6Vjg_FCi? z4W)y8K|{N+7xu_b?5Q2tp*_aW9rTMaq?DSsrVu+rd~J}hE1ki{8Q_4DpSuf+7N=y0 z&lbmI*d0+cIw7C&8TouX>b8vuC7%rP5n-@XYJN3AXB2Qkjq~PBh|f&&!8{IOB&X(2 zH9yyb7aQ|uSdryo%OvNrl!(4VCh<(%jlKg>o+p(VLEZu+SU49}D`X?;9hV2J6#b@5xoQzr_H2o5@^1L}hMUELzT^@ZjjKOo0;;PSc-R=y16 zZ?GMY#vgK8*szEP4+cZTEn{%f2k_E z27Gde+C~f)Fg^jqZfsd{i2;6w@jVpRk!@);Z(!Q^0V_`j7DaAW9TdZ@cIt4a4szZaa^^aU29qDr;ABm46G?-=na2}Ferp=!isDL5 zZsRR-8*h`__!TcbYL6zj@e8?){|UK0{(#)d@5!y&&_(q^Zq+tjEH`wq+|b2RliLz5 zFqaQCU2wY8dG2R6eWA(3ua&TB6J>0#%pV>3Z zdyofc0!I`ut`SP$kiJ3WHi#-0<433_` z)YOv0bAAFn?dFnNRNv(ebZf$J9m~5X4;HB}|KgQLUj9wtTU0ot`o1rAx!kOPE}Fw8 zS~Q^pvJt_F1Mf4=n%)ASw`5Ik|GTcX!Dzk1YQ^WUvs*ob65M#*8Pl}n#sj~2z;Kp3 z#wt>!wBemdQe1%Fa@<6G*Tw3BO6(?)=)j$C-mo1S$t$oENe=yhLb-k<8_;yI4OzB} zRnJ39Vd(ZadQJ$E_Fo6+T+OyM?w0=_W4@|s1;9o}-pE(zujhQpQ&}rb!wtIwq}*=X z4FSKo$AySPF)Nk{6YIBX;rZfke?Eikq=c+ENp6^52>r$^5|&2ANW^K%_#LYXv7c8e z=vGa#hyxfcmO0B{UVkpiG+<$zvOo;WqJY`6)K6l6B8Kp~K2ezpCd|@8%tl_2EiSSo zFA^|v1uq>WUSe{a+%Cnisy&!<^nU5?i#QLL2@C+6O z9mvZ6hkhC(4R=nr5iF#GH6&3&)`F6DcbF}Sh6I^7IhzV|9hOnAbbP~0)_aTc?G-T zUOp0`CmZu63}>tmJ`@(Gu)SWMGnfEAsi4IU)bR<5*jr~_#!;-Z^EjQ<&VItC4B8MT z8B`^L%rDim_gH$+=1MruU~n)H8CPxfm(bCv7eR<84hDk()HUc0oPGxaFZ!1Rx^{U0 z&VK*U?e~RBheyXbhhXsb4|_d`A?>3*L0l+t&uz4z32}iM0zT**`+0@&e*in8G#?BP F000|7$0Ps% literal 0 HcmV?d00001 diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/data/index.htm b/libraries/ESP8266WebServer/examples/FSBrowser/data/index.htm new file mode 100644 index 000000000..4e1dc7d9b --- /dev/null +++ b/libraries/ESP8266WebServer/examples/FSBrowser/data/index.htm @@ -0,0 +1,97 @@ + + + + + + ESP Monitor + + + + +
+ + + + +
+
+
+
+ + \ No newline at end of file