como-servir-una-pagina-web-con-el-esp8266-desde-spiffs

How to serve a web page with ESP8266 or ESP32 from SPIFFS

  • 4 min

In this post, we will see how to configure a Web server that serves static content from the file system of the ESP8266 or ESP32 using the SPIFFS file system.

We will refer to the ESP8266, but the same code is compatible with the ESP32, adjusting the library names. At the end, you have the code for both ESP8266 and ESP32.

Remember that we have several posts dedicated to making a server with the ESP8266. On the other hand, in the previous post we introduced the SPIFFS file system.

Finally, it’s time to combine both things to, now yes, start really playing with this SoC. And although we still have a lot ahead of us, we are going to start unleashing the potential and enjoying the ESP8266.

From 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 that.

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 functionality is achieved through the served JavaScript code and calls to the Backend.

But well, 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 the one we saw in the previous post, with the difference 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();
}
Copied!

On the other hand, we have modified the ‘Server.hpp’ file to define routing when the address is not found. Since we don’t have any other routing to an Endpoint, it will happen in all cases.

In the Callback function, first, we check if a file exists in SPIFFS that matches the request, with the function ‘HandleFileRead’. If it doesn’t 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");
}
Copied!

Finally, we have included the file ‘ESP8266_Utils_Server’, which contains the function HandleFileRead, and the necessary functions to serve the file from 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;
}
Copied!

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 above files located.

In this folder, we place a file called ‘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>
Copied!

Result

If we access the ESP8266 from the browser, we will see our simple (and at the same time brand new) web page served from the ESP8266’s SPIFFS. Congratulations!

esp8266-servidor-spiffs-hello-world

While in the serial port we can verify that we have indeed received the request.

esp8266-servidor-spiffs-serial-port

Is this over here? No, not at all! We have just started! In the next post, we will see how to improve our code by serving Gzip compressed files. That’s the next post!

Download the code

All the code from this post is available for download on Github.

github-full

Version for ESP8266: https://github.com/luisllamasbinaburo/ESP8266-Examples

Version for ESP32: https://github.com/luisllamasbinaburo/ESP32-Examples