{"id":75782,"date":"2018-10-19T09:54:11","date_gmt":"2018-10-19T09:54:11","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=75782"},"modified":"2019-08-22T13:29:10","modified_gmt":"2019-08-22T13:29:10","slug":"esp32-web-server-spiffs-spi-flash-file-system","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-web-server-spiffs-spi-flash-file-system\/","title":{"rendered":"ESP32 Web Server using SPIFFS (SPI Flash File System)"},"content":{"rendered":"\n<p>In this tutorial we&#8217;ll show you how to build a web server that serves HTML and CSS files stored on the ESP32 filesystem. Instead of having to write the HTML and CSS text into the Arduino sketch, we&#8217;ll create separated HTML and CSS files.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75806\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<p>For demonstration purposes, the web server we&#8217;ll build controls an ESP32 output, but it can be easily adapted for other purposes like displaying sensor readings.<\/p>\n\n\n\n<p><strong>Recommended reading:<\/strong>\u00a0<a href=\"https:\/\/randomnerdtutorials.com\/esp8266-web-server-spiffs-nodemcu\/\">ESP8266 Web Server using SPIFFS<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32&nbsp;Filesystem Uploader Plugin<\/h2>\n\n\n\n<p>To follow this tutorial you should have the ESP32&nbsp;Filesystem Uploader plugin installed in your Arduino IDE. If you haven&#8217;t, follow the next tutorial to install it first:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/install-esp32-filesystem-uploader-arduino-ide\/\">Install ESP32 Filesystem Uploader on Arduino IDE<\/a><\/li><\/ul>\n\n\n\n<p><strong>Note:<\/strong> make sure you have the latest Arduino IDE installed, as well as the ESP32 add-on for the Arduino IDE. If you don&#8217;t, follow one of the next tutorials to install it:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/installing-the-esp32-board-in-arduino-ide-windows-instructions\/\"><strong>Windows<\/strong>&nbsp;instructions \u2013 Installing the ESP32 Board in Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/installing-the-esp32-board-in-arduino-ide-mac-and-linux-instructions\/\"><strong>Mac and Linux<\/strong>&nbsp;instructions \u2013 Installing the ESP32 Board in Arduino IDE<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>Before going straight to the project, it&#8217;s important to outline what our web server will do, so that it is easier to understand.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"477\" height=\"486\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-async-web-server.png?resize=477%2C486&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75786\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-async-web-server.png?w=477&amp;quality=100&amp;strip=all&amp;ssl=1 477w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-async-web-server.png?resize=294%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 294w\" sizes=\"(max-width: 477px) 100vw, 477px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>The web server you\u2019ll build controls an LED connected to the ESP32 GPIO 2. This is the ESP32 on-board LED. You can control any other GPIO;<\/li><li>The web server page shows two buttons: ON and OFF &#8211; to turn GPIO 2 on and off;<\/li><li>The web server page also shows the current GPIO state.<\/li><\/ul>\n\n\n\n<p>The following figure shows a simplified diagram to demonstrate how everything works.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"1200\" height=\"479\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/async-web-server-spiffs.png?resize=1200%2C479&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75788\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/async-web-server-spiffs.png?w=1220&amp;quality=100&amp;strip=all&amp;ssl=1 1220w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/async-web-server-spiffs.png?resize=300%2C120&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/async-web-server-spiffs.png?resize=768%2C307&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/async-web-server-spiffs.png?resize=1024%2C409&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/async-web-server-spiffs.png?resize=250%2C100&amp;quality=100&amp;strip=all&amp;ssl=1 250w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>The ESP32 runs a web server code based on the <a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncWebServer library<\/a>;<\/li><li>The HTML and CSS files are stored on the ESP32 SPIFFS (Serial Peripheral Interface Flash File System);<\/li><li>When you make a request on a specific URL using your browser, the ESP32 responds with the requested files;<\/li><li>When you click the ON button, you are redirected to the root URL followed by <strong>\/on<\/strong> and the LED is turned on;<\/li><li>When you click the OFF button, you are redirected to the root URL followed by <strong>\/off<\/strong> and the LED is turned off;<\/li><li>On the web page, there is a placeholder for the GPIO state. The placeholder for the GPIO state is written directly in the HTML file between % signs, for example <strong>%STATE%<\/strong>.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Libraries<\/h2>\n\n\n\n<p>In most of our projects we\u2019ve created the HTML and CSS files for the web server as a String directly on the Arduino sketch. With SPIFFS, you can write the HTML and CSS in separated files and save them on the ESP32 filesystem.<\/p>\n\n\n\n<p>One of the easiest ways to build a web server using files from the filesystem is by using the ESPAsyncWebServer library. The ESPAsyncWebServer library is well documented on its GitHub page. For more information about that library, check the following link:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\">https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer<\/a><\/li><\/ul>\n\n\n\n<p><strong>Installing the ESPAsyncWebServer library<\/strong><\/p>\n\n\n\n<p>Follow the next steps to install the <a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncWebServer<\/a> library:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\/archive\/master.zip\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Click here to download<\/a>&nbsp;the ESPAsyncWebServer library. You should have a .zip folder in your Downloads folder<\/li><li>Unzip the .zip folder and you should get ESPAsyncWebServer-master folder<\/li><li>Rename your folder from <del>ESPAsyncWebServer-master<\/del>&nbsp;to ESPAsyncWebServer<\/li><li>Move the ESPAsyncWebServer&nbsp;folder to your Arduino IDE installation libraries folder<\/li><\/ol>\n\n\n\n<p><strong>Installing the&nbsp;Async TCP Library for ESP32<\/strong><\/p>\n\n\n\n<p>The <a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncWebServer\" target=\"_blank\" rel=\"noreferrer noopener\">ESPAsyncWebServer<\/a> library requires the <a href=\"https:\/\/github.com\/me-no-dev\/AsyncTCP\" target=\"_blank\" rel=\"noreferrer noopener\">AsyncTCP<\/a> library to work. Follow the next steps to install that library:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/me-no-dev\/AsyncTCP\/archive\/master.zip\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Click here to download<\/a>&nbsp;the AsyncTCP library. You should have a .zip folder in your Downloads folder<\/li><li>Unzip the .zip folder and you should get AsyncTCP-master folder<\/li><li>Rename your folder from <del>AsyncTCP-master<\/del>&nbsp;to AsyncTCP<\/li><li>Move the AsyncTCPfolder to your Arduino IDE installation libraries folder<\/li><li>Finally, re-open your Arduino IDE<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Organizing your Files<\/h2>\n\n\n\n<p>To build the web server you need three different files. The Arduino sketch, the HTML file and the CSS file. The HTML and CSS files should be saved inside a folder called <strong>data<\/strong> inside the Arduino sketch folder, as shown below:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"708\" height=\"370\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/folder-organization-async-spiffs.png?resize=708%2C370&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75791\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/folder-organization-async-spiffs.png?w=708&amp;quality=100&amp;strip=all&amp;ssl=1 708w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/folder-organization-async-spiffs.png?resize=300%2C157&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 708px) 100vw, 708px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the HTML File<\/h2>\n\n\n\n<p>The HTML for this project is very simple. We just need to create a heading for the web page, a paragraph to display the GPIO state and two buttons.<\/p>\n\n\n\n<p>Create an <em>index.html<\/em>&nbsp;file with the following content or <a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\">download all the project files here<\/a>:<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-html\">&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n  &lt;title&gt;ESP32 Web Server&lt;\/title&gt;\n  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n  &lt;link rel=&quot;icon&quot; href=&quot;data:,&quot;&gt;\n  &lt;link rel=&quot;stylesheet&quot; type=&quot;text\/css&quot; href=&quot;style.css&quot;&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n  &lt;h1&gt;ESP32 Web Server&lt;\/h1&gt;\n  &lt;p&gt;GPIO state: &lt;strong&gt; %STATE%&lt;\/strong&gt;&lt;\/p&gt;\n  &lt;p&gt;&lt;a href=&quot;\/on&quot;&gt;&lt;button class=&quot;button&quot;&gt;ON&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\n  &lt;p&gt;&lt;a href=&quot;\/off&quot;&gt;&lt;button class=&quot;button button2&quot;&gt;OFF&lt;\/button&gt;&lt;\/a&gt;&lt;\/p&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server\/data\/index.html\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>Because we&#8217;re using CSS and HTML in different files, we need to reference the CSS file on the HTML text. The following line should be added between the &lt;head&gt; &lt;\/head&gt; tags:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;link rel=\"stylesheet\" type=\"text\/css\" href=\"style.css\"><\/code><\/pre>\n\n\n\n<p>The &lt;link&gt; tag tells the HTML file that you\u2019re using an external style sheet to format how the page looks. The <strong>rel<\/strong> attribute specifies the nature of the external file, in this case that it is a <strong>stylesheet<\/strong>\u2014the CSS file\u2014that will be used to alter the appearance of the page.<\/p>\n\n\n\n<p>The <strong>type<\/strong> attribute is set to <strong>&#8220;text\/css&#8221;<\/strong> to indicate that you\u2019re using a CSS file for the styles. The <strong>href<\/strong> attribute indicates the file location; since both the CSS and HTML files will be in the same folder, you just need to reference the filename: <strong>style.css<\/strong>.<\/p>\n\n\n\n<p>In the following line, we write the first heading of our web page. In this case we have &#8220;ESP32 Web Server&#8221;. You can change the heading to any text you want:<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;h1>ESP32 Web Server&lt;\/h1><\/code><\/pre>\n\n\n\n<p>Then, we add a paragraph with the text &#8220;GPIO state: &#8221; followed by the GPIO state. Because the GPIO state changes accordingly to the state of the GPIO, we can add a placeholder that will then be replaced for whatever value we set on the Arduino sketch.<\/p>\n\n\n\n<p>To add placeholder we use <strong>%<\/strong> signs. To create a placeholder for the state, we can use <span class=\"rnthl rntliteral\">%STATE%<\/span>, for example.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p>GPIO state: &lt;strong>%STATE%&lt;\/strong>&lt;\/p><\/code><\/pre>\n\n\n\n<p>Attributing a value to the <span class=\"rnthl rntliteral\">STATE<\/span> placeholder is done in the Arduino sketch.<\/p>\n\n\n\n<p>Then, we create an ON and an OFF buttons. When you click the on button, we redirect the web page to to root followed by <span class=\"rnthl rntliteral\">\/on<\/span> url. When you click the off button you are redirected to the <span class=\"rnthl rntliteral\">\/off<\/span> url.<\/p>\n\n\n\n<pre class=\"wp-block-code language-html\"><code>&lt;p>&lt;a href=\"\/on\">&lt;button class=\"button\">ON&lt;\/button>&lt;\/a>&lt;\/p>\n&lt;p>&lt;a href=\"\/off\">&lt;button class=\"button button2\">OFF&lt;\/button>&lt;\/a>&lt;\/p><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the CSS file<\/h2>\n\n\n\n<p>Create the<em> style.css file<\/em> with the following content or <a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\">download all the project files here<\/a>:<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">html {\n  font-family: Helvetica;\n  display: inline-block;\n  margin: 0px auto;\n  text-align: center;\n}\nh1{\n  color: #0F3376;\n  padding: 2vh;\n}\np{\n  font-size: 1.5rem;\n}\n.button {\n  display: inline-block;\n  background-color: #008CBA;\n  border: none;\n  border-radius: 4px;\n  color: white;\n  padding: 16px 40px;\n  text-decoration: none;\n  font-size: 30px;\n  margin: 2px;\n  cursor: pointer;\n}\n.button2 {\n  background-color: #f44336;\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server\/data\/style.css\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>This is just a basic CSS file to set the font size, style and color of the buttons and align the page. We won&#8217;t explain how CSS works. A good place to learn about CSS is the <a href=\"https:\/\/www.w3schools.com\/css\/default.asp\" target=\"_blank\" rel=\"noreferrer noopener\">W3Schools website<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arduino Sketch<\/h2>\n\n\n\n<p>Copy the following code to the Arduino IDE or <a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\">download all the project files here<\/a>. Then, you need to type your network credentials (SSID and password) to make it work.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*********\n  Rui Santos\n  Complete project details at https:\/\/randomnerdtutorials.com  \n*********\/\n\n\/\/ Import required libraries\n#include &quot;WiFi.h&quot;\n#include &quot;ESPAsyncWebServer.h&quot;\n#include &quot;SPIFFS.h&quot;\n\n\/\/ Replace with your network credentials\nconst char* ssid = &quot;REPLACE_WITH_YOUR_SSID&quot;;\nconst char* password = &quot;REPLACE_WITH_YOUR_PASSWORD&quot;;\n\n\/\/ Set LED GPIO\nconst int ledPin = 2;\n\/\/ Stores LED state\nString ledState;\n\n\/\/ Create AsyncWebServer object on port 80\nAsyncWebServer server(80);\n\n\/\/ Replaces placeholder with LED state value\nString processor(const String&amp; var){\n  Serial.println(var);\n  if(var == &quot;STATE&quot;){\n    if(digitalRead(ledPin)){\n      ledState = &quot;ON&quot;;\n    }\n    else{\n      ledState = &quot;OFF&quot;;\n    }\n    Serial.print(ledState);\n    return ledState;\n  }\n  return String();\n}\n \nvoid setup(){\n  \/\/ Serial port for debugging purposes\n  Serial.begin(115200);\n  pinMode(ledPin, OUTPUT);\n\n  \/\/ Initialize SPIFFS\n  if(!SPIFFS.begin(true)){\n    Serial.println(&quot;An Error has occurred while mounting SPIFFS&quot;);\n    return;\n  }\n\n  \/\/ Connect to Wi-Fi\n  WiFi.begin(ssid, password);\n  while (WiFi.status() != WL_CONNECTED) {\n    delay(1000);\n    Serial.println(&quot;Connecting to WiFi..&quot;);\n  }\n\n  \/\/ Print ESP32 Local IP Address\n  Serial.println(WiFi.localIP());\n\n  \/\/ Route for root \/ web page\n  server.on(&quot;\/&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(SPIFFS, &quot;\/index.html&quot;, String(), false, processor);\n  });\n  \n  \/\/ Route to load style.css file\n  server.on(&quot;\/style.css&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    request-&gt;send(SPIFFS, &quot;\/style.css&quot;, &quot;text\/css&quot;);\n  });\n\n  \/\/ Route to set GPIO to HIGH\n  server.on(&quot;\/on&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    digitalWrite(ledPin, HIGH);    \n    request-&gt;send(SPIFFS, &quot;\/index.html&quot;, String(), false, processor);\n  });\n  \n  \/\/ Route to set GPIO to LOW\n  server.on(&quot;\/off&quot;, HTTP_GET, [](AsyncWebServerRequest *request){\n    digitalWrite(ledPin, LOW);    \n    request-&gt;send(SPIFFS, &quot;\/index.html&quot;, String(), false, processor);\n  });\n\n  \/\/ Start server\n  server.begin();\n}\n \nvoid loop(){\n  \n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server\/ESP32_Async_Web_Server.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>First, include the necessary libraries:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include \"WiFi.h\" \n#include \"ESPAsyncWebServer.h\" \n#include \"SPIFFS.h\"<\/code><\/pre>\n\n\n\n<p>You need to type your network credentials in the following variables:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const char* ssid = \"REPLACE_WITH_YOUR_SSID\"; \nconst char* password = \"REPLACE_WITH_YOUR_PASSWORD\";<\/code><\/pre>\n\n\n\n<p>Next, create a variable that refers to GPIO 2 called <span class=\"rnthl rntliteral\">ledPin<\/span>, and a String variable to hold the led state: <span class=\"rnthl rntliteral\">ledState<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>const int ledPin = 2;\nString ledState;<\/code><\/pre>\n\n\n\n<p>Create an <span class=\"rnthl rntliteral\">AsynWebServer<\/span> object called <span class=\"rnthl rntliteral\">server<\/span> that is listening on port 80.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>AsyncWebServer server(80);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">processor()<\/h3>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">processor()<\/span> function is what will attribute a value to the placeholder we&#8217;ve created on the HTML file. It accepts as argument the placeholder and should return a String that will replace the placeholder. The <span class=\"rnthl rntliteral\">processor()<\/span> function should have the following structure:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String processor(const String&amp; var){\n  Serial.println(var);\n  if(var == \"STATE\"){\n    if(digitalRead(ledPin)){\n      ledState = \"ON\";\n    }\n    else{\n      ledState = \"OFF\";\n    }\n    Serial.print(ledState);\n    return ledState;\n  }\n  return String();\n}<\/code><\/pre>\n\n\n\n<p>This function first checks if the placeholder is the <span class=\"rnthl rntliteral\">STATE<\/span> we&#8217;ve created on the HTML file.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(var == \"STATE\"){<\/code><\/pre>\n\n\n\n<p>If it is, then, accordingly to the LED state, we set the <span class=\"rnthl rntliteral\">ledState<\/span> variable to either ON or OFF.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(digitalRead(ledPin)){\n  ledState = \"ON\";\n}\nelse{\n  ledState = \"OFF\";\n}<\/code><\/pre>\n\n\n\n<p>Finally, we return the <span class=\"rnthl rntliteral\">ledState<\/span> variable. This replaces the placeholder with the <span class=\"rnthl rntliteral\">ledState<\/span> string value.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>return ledState;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">setup()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, start by initializing the Serial Monitor and setting the GPIO as an output.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Serial.begin(115200);\npinMode(ledPin, OUTPUT);<\/code><\/pre>\n\n\n\n<p>Initialize SPIFFS:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>if(!SPIFFS.begin(true)){\n  Serial.println(\"An Error has occurred while mounting SPIFFS\");\n  return;\n}<\/code><\/pre>\n\n\n\n<p><strong>Wi-Fi connection<\/strong><\/p>\n\n\n\n<p>Connect to Wi-Fi and print the ESP32 IP address:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>WiFi.begin(ssid, password);\nwhile (WiFi.status() != WL_CONNECTED) {\n  delay(1000);\n  Serial.println(\"Connecting to WiFi..\");\n}\nSerial.println(WiFi.localIP());<\/code><\/pre>\n\n\n\n<p><strong>Async Web Server<\/strong><\/p>\n\n\n\n<p>The ESPAsyncWebServer library allows us to configure the routes where the server will be listening for incoming HTTP requests and execute functions when a request is received on that route. For that, use the <span class=\"rnthl rntliteral\">on()<\/span> method on the server object as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send(SPIFFS, \"\/index.html\", String(), false, processor);\n});<\/code><\/pre>\n\n\n\n<p>When the server receives a request on the root &#8220;<strong>\/<\/strong>&#8221; URL, it will send the <em>index.html<\/em> file to the client. The last argument of the <span class=\"rnthl rntliteral\">send()<\/span> function is the processor, so that we are able to replace the placeholder for the value we want &#8211; in this case the <span class=\"rnthl rntliteral\">ledState<\/span>.<\/p>\n\n\n\n<p>Because we&#8217;ve referenced the CSS file on the HTML file, the client will make a request for the CSS file. When that happens, the CSS file is sent to the client:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/style.css\", HTTP_GET, [](AsyncWebServerRequest *request){\n  request->send(SPIFFS, \"\/style.css\",\"text\/css\");\n});<\/code><\/pre>\n\n\n\n<p>Finally, you need to define what happens on the <span class=\"rnthl rntliteral\">\/on<\/span> and <span class=\"rnthl rntliteral\">\/off<\/span> routes. When a request is made on those routes, the LED is either turned on or off, and the ESP32 serves the HTML file.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.on(\"\/on\", HTTP_GET, [](AsyncWebServerRequest *request){\n  digitalWrite(ledPin, HIGH);\n  request->send(SPIFFS, \"\/index.html\", String(),false, processor);\n});\nserver.on(\"\/off\", HTTP_GET, [](AsyncWebServerRequest *request){\n  digitalWrite(ledPin, LOW);\n  request->send(SPIFFS, \"\/index.html\", String(),false, processor);\n});<\/code><\/pre>\n\n\n\n<p>In the end, we use the <span class=\"rnthl rntliteral\">begin()<\/span> method on the <span class=\"rnthl rntliteral\">server<\/span> object, so that the server starts listening for incoming clients.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>server.begin();<\/code><\/pre>\n\n\n\n<p>Because this is an asynchronous web server, you can define all the requests in the <span class=\"rnthl rntliteral\">setup()<\/span>. Then, you can add other code to the <span class=\"rnthl rntliteral\">loop()<\/span> while the server is listening for incoming clients.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Uploading Code and Files<\/h2>\n\n\n\n<p>Save the code as <em>Async_ESP32_Web_Server<\/em> or&nbsp;<a href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-Course\/raw\/master\/code\/SPIFFS\/ESP32_Async_Web_Server.zip\" target=\"_blank\" rel=\"noreferrer noopener\">download all the project files here<\/a>. Go to <strong>Sketch<\/strong> &gt; <strong>Show Sketch Folder<\/strong>, and create a folder called <strong>data<\/strong>. Inside that folder you should save the HTML and CSS files.<\/p>\n\n\n\n<p>Then, upload the code to your ESP32 board. Make sure you have the right board and COM port selected. Also, make sure you&#8217;ve added your networks credentials to the code.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"34\" height=\"29\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2016\/12\/arduino-ide-upload-button.png?resize=34%2C29&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-65439\"\/><\/figure><\/div>\n\n\n\n<p>After uploading the code, you need to upload the files. Go to <strong>Tools&nbsp;<\/strong>&gt; <strong>ESP32 Data Sketch Upload<\/strong> and wait for the files to be uploaded.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"295\" height=\"391\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/sketch-data-upload.png?resize=295%2C391&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75771\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/sketch-data-upload.png?w=295&amp;quality=100&amp;strip=all&amp;ssl=1 295w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/sketch-data-upload.png?resize=226%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 226w\" sizes=\"(max-width: 295px) 100vw, 295px\" \/><\/figure><\/div>\n\n\n\n<p>When everything is successfully uploaded, open the Serial Monitor at a baud rate of 115200. Press the ESP32 &#8220;<strong>ENABLE<\/strong>&#8221; button, and it should print the ESP32 IP address.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"574\" height=\"362\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-ip-address.png?resize=574%2C362&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75787\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-ip-address.png?w=574&amp;quality=100&amp;strip=all&amp;ssl=1 574w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-ip-address.png?resize=300%2C189&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 574px) 100vw, 574px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>Open your browser and type the ESP32 IP address. Press the ON and OFF buttons to control the ESP32 on-board LED. Also, check that the GPIO state is being updated correctly.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs-example.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-75793\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs-example.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs-example.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs-example.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs-example.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>Using SPI Flash File System (SPIFFS) is specially useful to store HTML and CSS files to serve to a client &#8211; instead of having to write all the code inside the Arduino sketch.<\/p>\n\n\n\n<p>The ESPAsyncWebServer library allows you to build a web server by running a specific function in response to a specific request. You can also add placeholders to the HTML file that can be replaced with variables &#8211; like sensor readings, or GPIO states, for example.<\/p>\n\n\n\n<p>If you liked this project, you may also like:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-with-bme280-mini-weather-station\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32 Web Server with BME280 \u2013 Mini Weather Station<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-arduino-ide\/\">ESP32 Web Server \u2013 Arduino IDE<\/a><\/li><li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-micropython-esp32-esp8266\/\">Getting Started with MicroPython on ESP32 and ESP8266<\/a><\/li><\/ul>\n\n\n\n<p><em>This is an excerpt from our course:&nbsp;<strong><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE<\/a><\/strong>. If you like ESP32 and you want to learn more, we recommend enrolling in&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE course<\/a>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial we&#8217;ll show you how to build a web server that serves HTML and CSS files stored on the ESP32 filesystem. Instead of having to write the HTML &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 Web Server using SPIFFS (SPI Flash File System)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-web-server-spiffs-spi-flash-file-system\/#more-75782\" aria-label=\"Read more about ESP32 Web Server using SPIFFS (SPI Flash File System)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":75806,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-75782","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2018\/10\/esp32-web-server-spiffs.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/75782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=75782"}],"version-history":[{"count":0,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/75782\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/75806"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=75782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=75782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=75782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}