Skip to content

Commit cec2fb4

Browse files
committed
Merge pull request #298 from ficeto/esp8266
add gzip content support for HTML File streaming
2 parents 182ce10 + 3178e06 commit cec2fb4

File tree

13 files changed

+1277
-3
lines changed

13 files changed

+1277
-3
lines changed

hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/****
2+
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3+
* Created 2015 by Skurydin Alexey
4+
* http://github.com/anakod/Sming
5+
* All files of the Sming Core are provided under the LGPL v3 license.
6+
****/
7+
18
#include "spiffs_esp8266.h"
29
#include "spi_flash.h"
310
#include "esp8266_peri.h"
@@ -152,6 +159,6 @@ uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ){
152159

153160
//shorthand when start and end addresses of the sector are not needed
154161
uint32_t flashmem_get_sector_of_address( uint32_t addr ){
155-
return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE;;
162+
return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE;
156163
}
157164

hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_esp8266.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/****
2+
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3+
* Created 2015 by Skurydin Alexey
4+
* http://github.com/anakod/Sming
5+
* All files of the Sming Core are provided under the LGPL v3 license.
6+
****/
7+
18
#ifndef SYSTEM_FLASHMEM_H_
29
#define SYSTEM_FLASHMEM_H_
310

@@ -17,7 +24,6 @@ The small 4KB sectors allow for greater flexibility in applications that require
1724
#define SPIFFS_API_DBG_V(fmt, ...) //os_printf(fmt, ##__VA_ARGS__)
1825
#define SPIFFS_API_DBG_E(fmt, ...) //os_printf("ERROR: " fmt , ##__VA_ARGS__)
1926

20-
#define INTERNAL_FLASH_PAGE_SIZE 256
2127
#define INTERNAL_FLASH_SECTOR_SIZE 4096
2228
#define INTERNAL_FLASH_START_ADDRESS 0x40200000
2329

@@ -27,7 +33,6 @@ The small 4KB sectors allow for greater flexibility in applications that require
2733
extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size );
2834
extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size );
2935
extern bool flashmem_erase_sector( uint32_t sector_id );
30-
uint32_t flashmem_find_sector( uint32_t address, uint32_t *pstart, uint32_t *pend );
3136
uint32_t flashmem_get_sector_of_address( uint32_t addr );
3237

3338
#ifdef __cplusplus
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
/*
2+
FSWebServer - Example WebServer with SPIFFS backend for esp8266
3+
4+
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
5+
This file is part of the ESP8266WebServer library for Arduino environment.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
21+
upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE)
22+
!!! This will erase any previous SPIFFS data you may have!
23+
!!! Make Backups First !!!
24+
if you do not have it, get it at : <<<FILL THIS
25+
access the sample web page at http://esp8266fs.local
26+
edit the page by going to http://esp8266fs.local/edit
27+
28+
*/
29+
#include <ESP8266WiFi.h>
30+
#include <WiFiClient.h>
31+
#include <ESP8266WebServer.h>
32+
#include <ESP8266mDNS.h>
33+
#include <FileSystem.h>
34+
35+
#define DBG_OUTPUT_PORT Serial
36+
37+
const char* ssid = "**********";
38+
const char* password = "**********";
39+
const char* hostname = "esp8266fs";
40+
41+
MDNSResponder mdns;
42+
ESP8266WebServer server(80);
43+
//holds the current upload
44+
FSFile fsUploadFile;
45+
46+
//format bytes
47+
char *formatBytes(size_t bytes){
48+
if (bytes < 1024){
49+
return (char *)String(String(bytes)+"B").c_str();
50+
} else if(bytes < (1024 * 1024)){
51+
return (char *)String(String(bytes/1024.0)+"KB").c_str();
52+
} else if(bytes < (1024 * 1024 * 1024)){
53+
return (char *)String(String(bytes/1024.0/1024.0)+"MB").c_str();
54+
} else {
55+
return (char *)String(String(bytes/1024.0/1024.0/1024.0)+"GB").c_str();
56+
}
57+
}
58+
59+
String getContentType(String filename){
60+
if(server.hasArg("download")) return "application/octet-stream";
61+
else if(filename.endsWith(".htm")) return "text/html";
62+
else if(filename.endsWith(".css")) return "text/css";
63+
else if(filename.endsWith(".js")) return "application/javascript";
64+
else if(filename.endsWith(".png")) return "image/png";
65+
else if(filename.endsWith(".gif")) return "image/gif";
66+
else if(filename.endsWith(".jpg")) return "image/jpeg";
67+
else if(filename.endsWith(".ico")) return "image/x-icon";
68+
else if(filename.endsWith(".xml")) return "text/xml";
69+
else if(filename.endsWith(".pdf")) return "application/x-pdf";
70+
else if(filename.endsWith(".zip")) return "application/x-zip";
71+
else if(filename.endsWith(".gz")) return "application/x-gzip";
72+
return "text/plain";
73+
}
74+
75+
bool handleFileRead(String path){
76+
if(path.endsWith("/")) path += "index.htm";
77+
String contentType = getContentType(path);
78+
if(FS.exists((char *)(path+".gz").c_str()) || FS.exists((char *)path.c_str())){
79+
if(FS.exists((char *)(path+".gz").c_str()))
80+
path += ".gz";
81+
FSFile file = FS.open((char *)path.c_str());
82+
server.streamFile(file, contentType);
83+
file.close();
84+
return true;
85+
}
86+
return false;
87+
}
88+
89+
void handleFileUpdate(){
90+
if(server.uri() != "/edit") return;
91+
HTTPUpload& upload = server.upload();
92+
if(upload.status == UPLOAD_FILE_START){
93+
String filename = upload.filename;
94+
DBG_OUTPUT_PORT.print("Upload Name: "); DBG_OUTPUT_PORT.println(filename);
95+
fsUploadFile = FS.open((char *)filename.c_str(), FSFILE_OVERWRITE);
96+
filename = String();
97+
} else if(upload.status == UPLOAD_FILE_WRITE){
98+
//DBG_OUTPUT_PORT.print("Upload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
99+
if(fsUploadFile)
100+
fsUploadFile.write(upload.buf, upload.currentSize);
101+
} else if(upload.status == UPLOAD_FILE_END){
102+
if(fsUploadFile)
103+
fsUploadFile.close();
104+
DBG_OUTPUT_PORT.print("Upload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
105+
}
106+
}
107+
108+
void handleFileDelete(){
109+
if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS");
110+
String path = server.arg(0);
111+
if(path == "/")
112+
return server.send(500, "text/plain", "BAD PATH");
113+
if(!FS.exists((char *)(path.c_str())))
114+
return server.send(404, "text/plain", "FileNotFound");
115+
FS.remove((char *)path.c_str());
116+
server.send(200, "text/plain", "");
117+
path = String();
118+
}
119+
120+
void handleFileCreate(){
121+
if(server.args() == 0)
122+
return server.send(500, "text/plain", "BAD ARGS");
123+
String path = server.arg(0);
124+
if(path == "/")
125+
return server.send(500, "text/plain", "BAD PATH");
126+
if(FS.exists((char *)path.c_str()))
127+
return server.send(500, "text/plain", "FILE EXISTS");
128+
FSFile file = FS.open((char *)path.c_str(), FSFILE_OVERWRITE);
129+
if(file)
130+
file.close();
131+
else
132+
return server.send(500, "text/plain", "CREATE FAILED");
133+
server.send(200, "text/plain", "");
134+
path = String();
135+
}
136+
137+
void handleFileList() {
138+
if(!server.hasArg("dir")) return server.send(500, "text/plain", "BAD ARGS");
139+
String path = server.arg("dir");
140+
141+
FSFile entry;
142+
FSFile dir = FS.open((char *)path.c_str());
143+
path = String();
144+
if(!dir.isDirectory()){
145+
dir.close();
146+
server.send(500, "text/plain", "NOT DIR");
147+
return;
148+
}
149+
dir.rewindDirectory();
150+
151+
WiFiClient client = server.client();
152+
client.print("HTTP/1.1 200 OK\r\nContent-Type: text/json\r\nConnection: close\r\n\r\n");
153+
String output = "[";
154+
while(true){
155+
entry = dir.openNextFile();
156+
if (!entry) break;
157+
if(!FS.exists(entry.name())){
158+
os_printf("Entry[%s] Not Exists!\n", entry.name());
159+
entry.remove();
160+
entry.close();
161+
continue;
162+
}
163+
if(output != "[") output += ',';
164+
output += "{\"type\":\"";
165+
output += (entry.isDirectory())?"dir":"file";
166+
output += "\",\"name\":\"";
167+
output += String(entry.name()).substring(1);
168+
output += "\"}";
169+
entry.close();
170+
}
171+
dir.close();
172+
173+
output += "]";
174+
client.write(output.c_str(), output.length());
175+
output = String();
176+
uint16_t maxWait = HTTP_MAX_CLOSE_WAIT;
177+
while(client.connected() && maxWait--) {
178+
delay(1);
179+
}
180+
}
181+
182+
void setup(void){
183+
DBG_OUTPUT_PORT.begin(115200);
184+
DBG_OUTPUT_PORT.print("\n");
185+
186+
//SPIFFS INIT
187+
DBG_OUTPUT_PORT.printf("\n==== SPIFFS Info ====\n");
188+
DBG_OUTPUT_PORT.printf("FS Mount: %d\n", FS.mount());
189+
DBG_OUTPUT_PORT.printf("FS Size: %s\n", formatBytes(FS.size()));
190+
DBG_OUTPUT_PORT.printf("FS Bytes: total: %s, used: %s\n", formatBytes(FS.totalBytes()), formatBytes(FS.usedBytes()));
191+
DBG_OUTPUT_PORT.printf("FS Blocks: total: %d, free: %d, size: %s\n", FS.totalBlocks(), FS.freeBlocks(), formatBytes(FS.blockSize()));
192+
DBG_OUTPUT_PORT.printf("FS Pages: allocated: %d, deleted: %d, size: %s\n", FS.allocatedPages(), FS.deletedPages(), formatBytes(FS.pageSize()));
193+
FSFile entry;
194+
FSFile dir = FS.open((char *)"/");
195+
while(true){
196+
entry = dir.openNextFile();
197+
if (!entry) break;
198+
DBG_OUTPUT_PORT.printf("FS File: %s, type: %s, size: %s\n", entry.name(), (entry.isDirectory())?"dir":"file", formatBytes(entry.size()));
199+
entry.close();
200+
}
201+
dir.close();
202+
DBG_OUTPUT_PORT.printf("\n");
203+
204+
//WIFI INIT
205+
DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
206+
WiFi.begin(ssid, password);
207+
if(WiFi.waitForConnectResult() != WL_CONNECTED){
208+
DBG_OUTPUT_PORT.printf("Could not connect to %s\n", ssid);
209+
while(1) delay(500);
210+
}
211+
DBG_OUTPUT_PORT.print("Connected! IP address: ");
212+
DBG_OUTPUT_PORT.println(WiFi.localIP());
213+
214+
//mDNS INIT
215+
if (mdns.begin(hostname, WiFi.localIP()))
216+
DBG_OUTPUT_PORT.printf("mDNS responder started for %s.local\n", hostname);
217+
218+
//SERVER INIT
219+
//list directory
220+
server.on("/list", HTTP_GET, handleFileList);
221+
//load editor
222+
server.on("/edit", HTTP_GET, [](){
223+
if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound");
224+
});
225+
//create file
226+
server.on("/edit", HTTP_PUT, handleFileCreate);
227+
//delete file
228+
server.on("/edit", HTTP_DELETE, handleFileDelete);
229+
//called after file upload
230+
server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); });
231+
//called when a file is received inside POST data
232+
server.onFileUpload(handleFileUpdate);
233+
234+
//called when the url is not defined here
235+
//use it to load content from SPIFFS
236+
server.onNotFound([](){
237+
if(!handleFileRead(server.uri()))
238+
server.send(404, "text/plain", "FileNotFound");
239+
});
240+
241+
//get heap status, analog input value and all GPIO statuses in one json call
242+
server.on("/all", HTTP_GET, [](){
243+
String json = "{";
244+
json += "\"heap\":"+String(ESP.getFreeHeap());
245+
json += ", \"analog\":"+String(analogRead(A0));
246+
json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
247+
json += "}";
248+
server.send(200, "text/json", json);
249+
json = String();
250+
});
251+
server.begin();
252+
DBG_OUTPUT_PORT.println("HTTP server started");
253+
254+
}
255+
256+
void loop(void){
257+
server.handleClient();
258+
}

0 commit comments

Comments
 (0)