In this post we are going to see how to set up a Web server that serves static content from the file system of the ESP8266 or ESP32 from the SPIFFS file system.
We will refer to the ESP8266, but the same code is compatible for the ESP32, adjusting the name of the libraries. At the end you have the code for both the ESP8266 and the ESP32.
Remember that we have had several entries dedicated to making a server with the ESP8266. On the other hand, in the previous entry we presented the SPIFFS file system.
Finally, it’s time to put both things together to really start playing with this SoC. Although we still have a lot ahead, we are going to start taking advantage of and enjoying the ESP8266.
From the SPIFFS we can only serve static content. That is, content that does not change between requests. But that does not mean, by any means, that it is a simple text file. In fact, many modern websites are like this.
What we are going to do is serve files (html, css, js) in a similar way to how we do it on a “conventional” server. Normally, the client loads this content and the dynamic operation is achieved through the served JavaScript code and calls to the Backend.
But hey, let’s not get ahead of ourselves. We will see all that in due time. For now, how do we start?
Our main program is similar to what we saw in the previous entry, with the exception that we have added a reference to ‘FS.h’.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h> // Include the SPIFFS library
#include "config.h" // Replace with your network data
#include "Server.hpp"
#include "ESP8266_Utils.hpp"
void setup(void)
{
Serial.begin(115200);
SPIFFS.begin();
ConnectWiFi_STA();
InitServer();
}
void loop(void)
{
server.handleClient();
}
On the other hand, we have modified the ‘Server.hpp’ file to define a routing when the address is not found. Since we do not have any other routing to an Endpoint, it will occur in all cases.
In the Callback function, first of all, we check if there is a file in the SPIFFS that matches the request, with the ‘HandleFileRead’ function. If it does not exist, we return a 404, not found error.
ESP8266WebServer server(80);
#include "ESP8266_Utils_Server.hpp"
void handleNotFound() {
server.send(404, "text/plain", "Not found");
}
void InitServer()
{
server.onNotFound([]() { // If the client requests any URI
if (!HandleFileRead(server.uri())) // send it if it exists
handleNotFound(); // otherwise, respond with a 404 (Not Found) error
});
server.begin();
Serial.println("HTTP server started");
}
Finally, we have included the ‘ESP8266_Utils_Server’ file, which contains the HandleFileRead
function, and the necessary functions to serve the file from the SPIFFS.
String GetContentType(String filename)
{
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";
}
void ServeFile(String path)
{
File file = SPIFFS.open(path, "r");
size_t sent = server.streamFile(file, GetContentType(path));
file.close();
}
void ServeFile(String path, String contentType)
{
File file = SPIFFS.open(path, "r");
size_t sent = server.streamFile(file, contentType);
file.close();
}
bool HandleFileRead(String path)
{
if (path.endsWith("/")) path += "index.html";
Serial.println("handleFileRead: " + path);
if (SPIFFS.exists(path))
{
ServeFile(path);
return true;
}
Serial.println("\tFile Not Found");
return false;
}
We compile the code and upload it to our ESP8266. On the other hand, we create a folder called ‘data’ inside the folder where we have the previous files hosted.
In this folder, we call a file named ‘index.html’ with the following content.
<!DOCTYPE html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Hello world!</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>This is your web page. Congratulations!</h1>
</body>
</html>
Result
If we access our ESP8266 from the browser, we will see our simple (and at the same time splendid) web page served from the SPIFFS of the ESP8266. Congratulations!
While in the serial port we can check that we have indeed received the request.
Has this ended here? No, not by a long shot. We have just begun! In the next entry we will see how to improve our code by serving compressed files in Gzip. That’s the next entry!
Download the code
All the code from this post is available for download on Github.
Version for the ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples
Version for the ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples