ESP32 Web Server Hosting Files from MicroSD Card

In this tutorial, you’ll learn how to build an ESP32 web server to serve files from a microSD card using a microSD card module that communicates using SPI protocol. You’ll learn how to serve your HTML, CSS, JavaScript files, images, and other assets saved on the microSD card. This can be especially useful if your files are too big to fit on the filesystem (SPIFFS), or it can also be more convenient depending on your project. To build the web server, we’ll use the ESPAsyncWebServer library.

ESP32 Web Server Hosting Files from MicroSD Card

If you want to build a web server with files from SPIFFS, follow the next tutorial instead:

Project Overview

To show you how to build a web server with files from a microSD card, we’ll build a simple HTML page that displays some text formatted with CSS. We’ll also serve a favicon. The following image shows the web page we’ll serve:

ESP32 Web Server with Files from microSD card
  • The web server is built using the ESPAsyncWebServer library;
  • The HTML, CSS, and favicon files are saved on the microSD card;
  • The microSD card communicates with the ESP32 via SPI communication protocol;
  • When the client makes a request to the ESP32, it serves the files saved on the microSD card;
  • You can apply what you’ll learn here to any web server project that you are working on.
ESP32 Web Server with Files from microSD Card How it Works

MicroSD Card Module

There are different microSD card modules compatible with the ESP32. We’re using the microSD card module sown in the following figure – it communicates using SPI communication protocol. You can use any other microSD card module with an SPI interface.

microSD card module for ESP32 ESP8266 Arduino SPI

Where to Buy?

You can click the link below to check different stores where you can get the microSD card module:

MicroSD card module for ESP32 ESP8266 Arduino SPI

MicroSD Card Module Pinout

The microSD card module communicates using SPI communication protocol. We’ll use the default ESP32 SPI pins as shown in the following table:

microSD card moduleESP32
3V33.3V
CSGPIO 5
MOSIGPIO 23
CLKGPIO 18
MISOGPIO 19
GNDGND

Recommended reading: ESP32 Pinout Reference: Which GPIO pins should you use?

Preparing the MicroSD Card

Before proceeding with the tutorial, make sure you format your microSD card as FAT32. Follow the next instructions to format your microSD card or use a software tool like SD Card Formater (compatible with Windows and Mac OS).

1. Insert the microSD card in your computer. Go to My Computer and right click on the SD card. Select Format as shown in figure below.

Preparing the MicroSD Card format microSD Card

2. A new window pops up. Select FAT32, press Start to initialize the formatting process and follow the onscreen instructions.

Preparing the MicroSD Card format microSD Card

After formatting the microSD card, you can paste the files used to build the web server there. We’ll move the index.html, style.css, and favicon.png files into there. Follow the next section to get your files.

HTML File

Create a file called index.html with the following content:

<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" type="text/css" href="style.css">
  <link rel="icon"  type="image/png" href="favicon.png">
  <title>ESP Web Server</title>
</head>
<body>
  <h1>Hello World!</h1>
  <p>This page was built with files from a microSD card.</p>
</body>
</html>

View raw code

CSS File

Create a file called style.css with the following content:

html {
    font-family: Arial; 
    text-align: center;
}
body {
    max-width: 400px; 
    margin:0px auto;
}

View raw code

Favicon

We’ll also serve a favicon. It is a png image with 15×15 pixels. You can use the same favicon as ours, or your own icon, or none favicon at all.

You can click on the following link to download the favicon:

Copy Files to MicroSD Card

After having all files prepared, open the microSD card directory and paste the files.

microSD Card Folder with Files to Build Web Server

Parts Required

ESP32 microSD card module wiring breadboard

For this tutorial you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic Diagram

Wire the microSD card module to the ESP32 as shown in the following schematic diagram. We’re using the default ESP32 SPI pins.

ESP32 microSD Card Module Wiring Diagram

Code

Copy the following code to your Arduino IDE.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-web-server-microsd-card/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

void initSDCard(){
  if(!SD.begin()){
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if(cardType == CARD_MMC){
    Serial.println("MMC");
  } else if(cardType == CARD_SD){
    Serial.println("SDSC");
  } else if(cardType == CARD_SDHC){
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
}

void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println(WiFi.localIP());
}

void setup() {
  Serial.begin(115200);
  initWiFi();
  initSDCard();

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SD, "/index.html", "text/html");
  });

  server.serveStatic("/", SD, "/");

  server.begin();
}

void loop() {
  
}

View raw code

Insert your network credentials in the following variables and the code should work straight away:

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

How the Code Works

We’ve covered how to build a web server with the ESP32 in previous tutorials. So, we’ll just take a look at the relevant parts for this tutorial.

Libraries

First, make sure you include the FS.h, SD.h and SPI.h libraries to be able to communicate with the microSD card and handle files.

#include "FS.h"
#include "SD.h"
#include "SPI.h"

Initialize MicroSD Card

The initSDCard() function initializes the microSD card on the default SPI pins.

void initSDCard(){
  if(!SD.begin()){
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    Serial.println("No SD card attached");
    return;
  }
  Serial.print("SD Card Type: ");
  if(cardType == CARD_MMC){
    Serial.println("MMC");
  } else if(cardType == CARD_SD){
    Serial.println("SDSC");
  } else if(cardType == CARD_SDHC){
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
}

Then, you need to call this function in the setup():

initSDCard();

Serve Files From microSD Card

When you access the ESP32 IP address on the root (/) URL, send the HTML file saved on the microSD card.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(SD, "/index.html", "text/html");
});

The first argument of the send() function is the filesystem where the files are saved. In this case, it is saved in the SD card (SD). The second argument is the path where the file is located /index.html). The third argument refers to the content type (text/html).

When the HTML file loads on your browser, it will request the CSS and the favicon files. These are static files saved on the same directory (SD). We can add the following line to serve static files in a directory when requested by the root URL. It serves the CSS and favicon files automatically.

server.serveStatic("/", SD, "/");

If your web server needs to handle more routes, you can add them to the setup(). Don’t forget to set SD as the first argument to the send() function. This way, it will look for the files in the microSD card.

It’s as simple as this. This can be applied to any other web server project.

Demonstration

After uploading the code, open the Serial Monitor at a baud rate of 115200. Press the on-board RST button.

You should get something similar on the Serial Monitor: the ESP32 IP address and information about the microSD card.

Web Server with Files from MicroSD card Serial Monitor IP Address

Open a browser on your local network and paste the ESP32 IP address. It will load the following web page with the files saved on the microSD card. Notice the favicon on the web browser title bar.

ESP32 Web Server with Files from microSD card

Wrapping Up

In this tutorial, you’ve learned how to build a web server with the ESP32 with files saved on the microSD card. Instead of writing the HTML, CSS, and JavaScript text directly on the Arduino sketch, you can save them on separate files on a microSD card. This can also be useful to store other data that you might want to display on your web server.

If you don’t have a microSD card module, you can save the files on the ESP32 filesystem (SPIFFS) if they fit. You might also like:

We hope you’ve found this tutorial useful.

Learn more about the ESP32 with our resources:



Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our newsletter!

55 thoughts on “ESP32 Web Server Hosting Files from MicroSD Card”

    • Hi.
      This is compatible with the ESP8266.
      You just need to include the ESP8266WiFi library and connect to the ESP8266 SPI pins.
      We’ll create a similar tutorial for the ESP8266 soon.
      Regards,
      Sara

      Reply
      • Hello.
        While trying to adapt this program for ESP8266 I’ve encountered some problem with the function: request->send(SD, “/index.html”, “text/html”);
        When I change “SD” to “LittleFS” it works correctly. Do you have any suggestion how to solve the problem?

        Reply
        • Hi.
          The pins to use the SD card with the ESP8266 are different.
          However, I’ve tried to use this approach with the ESP8266 without success until now :/
          So, at the moment I don’t have a solution for the ESP8266.
          I’m sorry that I can’t help much.
          Regards,
          Sara

          Reply
          • Thanks for your response.

            The hardware and its configuration are OK – I can write or read from SD card using another methods.

            I’ve figured out that it should be “SDFS” instead of “SD” for ESP8266. But now I have another problem – for “request->send(SDFS, “/index.htm”, “text/html”, processor);” the web site doesn’t appear in the browser but there is only a prompt to downloading the file to disk. I think that I should add somewhere response 200 (OK from server) but I don’t know how. Never ending story… 🙂

          • Hi.
            I remember that I also tried an approach that had the same result—instead of showing the page, it downloaded the file.
            At the moment, I’m not sure how to make it work with the ESP8266.
            Let us know if you find anything.
            Regards,
            Sara

  1. Cāk por cĕkh tạwxỳāng k̄ĥāng bn p̄hm mī khảt̄hām thī̀ xyāk ca t̄hām kạb khuṇ ẁā mạn rxngrạb kār tậng chụ̄̀x fịl̒ bæb yāw læa rxngrạb fịl̒ thī̀ mī nāms̄kul yāw mākkẁā 3 tạw xạks̄ʹr h̄rụ̄x mị̀ læa s̄ảh̄rạb krṇī k̄hxng ESP8266(p̄hm chı̂ Wemos D1 mini with SD card shield) p̄hm thdlxng d̂wy tạw xeng xỳāng ng̀āy«mị̀ nān mā nī̂ p̄hm phb ẁā welā chı̂ wĕb be rā sexr̒ chī̂ pị yạng tạw server(esp8266) bāng khrậng h̄rụ̄x xāc ca b̀xy«mạn dūh̄emụ̄xn ca mī xākār kĥāng læa meụ̄̀x peid h̄n̂āt̀āng serial monitor p̄hm k̆ phb kạb kār cæ̂ng xxk mā nı lạks̄ʹṇa keid khwām p̄hid phlād pramāṇ”exception” xarị thảnxng nận cnt̄hụng welā nī̂ p̄hm k̆ yạng mị̀kh̀xy ca k̄hêācı mạn nạk læa pherāa p̄hm mị̀kh̀xy ca mī welā cụng pl̀xy mạn xeā wị̂ k̀xn læa klạb mā reīyn rū̂ s̄ìng thī̀ mī xyū̀ nı ebook thī̀ p̄hm sụ̄̂x mā cāk khuṇ t̀x pị k̄hxxp̣hạy p̄hm mị̀kh̀xy kèng p̣hās̄ʹā xạngkvs̄ʹ p̄hm xeng k̆ phyāyām ca s̄ụ̄̀xs̄ār kạb khuṇ d̂wy p̣hās̄ʹā k̄hxng p̄hm læ̂w h̄ı̂ google pæl mạn h̄ı̂ pĕn p̣hās̄ʹā xạngkvs̄ʹ k̄hxbkhuṇ s̄ảh̄rạb khwām rū̂ dī«
    แสดงเพิ่ม
    753 / 5000
    ผลลัพธ์การแปล
    From the example project above
    I have a question that I want to ask you.
    Does it support long file names and does it support files with extensions more than 3 characters?

    And for the case of ESP8266 (I use Wemos D1 mini with SD card shield) I have easily tried it myself recently. I found that when I use my web browser to point to the server (esp8266).
    Sometimes or maybe often It appears to have freezes. And when I opened the serial monitor window, I got an error like “exception” and something like that. Until now, I have not fully understood it. And because I don’t have much time, I just leave it and go back and learn what is included in the ebook I bought from you.

    Sorry, I am not good at English.
    I also try to communicate with you in my language.
    And let google translate it to english

    Thank you for your kind knowledge

    Reply
    • Hi.
      I haven’t tried it with long filenames.
      It supports PNG extension (3 characters). I never tried it with an extension with more than 4 characters, but I don’t see why it would be a problem.
      If you’re trying to load a huge file using the ESP8266, it may not have enough processing power to do that. In that case, your project would benefit if you use an ESP32. However, it really depends on the file size.
      Regards,
      Sara

      Reply
  2. Excellent project. Thanks for sharing. One question, I have saved 4 audio files in the SD card. How to access these from my PC? I can access to webpage through local network’s private IP address but can’t access to the audio files. Please help!

    Reply
  3. Hi Sara,

    Thanks for all your excellent tutorials, unlike many I have found online, where the software will not even compile, or libraries will not load..

    I purchased a micro SD card from Banggood from your link. I noticed that this card seems to require 4.5 – 5.5 Volts to operate. However even after connecting Vcc to Vin on the ESP32, I was still greeted by a message telling me ‘Card Mount Failed’.

    I do not give up easily, & a little research found the solution. Connect a 10K resistor between GND & CS.

    Success!!

    It works fine now.

    Keep up the good work, & stay safe.

    Alan

    Reply
  4. Hallo Sar en Rui.
    This would be a great option as a Portal version. I don’t have the knowledge to program this myself. Do you have any plans for this? That would be nice. Greetings old man Bert

    Reply
  5. I found that the Micro Card Reader VCC should be connected to VIN on the ESP32. If connected to 3.3V, result is Card Mount failed. Also, the Webpage I have also uses PHP files. The CSS and JS files work, i.e., uploaded and main page looks okay. But if I try a clicking on a label which calls a PHP list function this is the result:
    192.168.1.64 is currently unable to handle this request.
    HTTP ERROR 500
    Is there a method to include PHP files when calling the initial html file.
    Appreciate your help. Thank You.
    Regards,
    Robert

    Reply
    • The simple answer is no, as far as I can tell. I’ve just tried it with a 193MB video file and I had time to read several RNT articles before it eventually loaded. It did get there in the end, though, so if you have got 10 minutes to spare, it may be OK.

      I don’t know what is the limiting factor – the SD card to ESP32 transfer or the ESP32 to the web client. I suspect the latter.

      Does anyone else have any experience of this?

      Reply
  6. Hello,

    This is a great example that you have made! I am having some errors during the compilation process. I have updated libraries with the latest ones for ESP32 and install the libraries that you have used in this example. I fixed some of them but there are two which I could not find any solution to them by searching on Google and decided to ask you.

    I use an ESP32 and the libraries I included as listed below.

    #include “WiFi.h”
    #include <AsyncTCP.h>
    #include “ESPAsyncWebServer.h”

    I have followed the steps you applied for the example but after compilation, I am having those errors:

    error: ‘class WiFiServer’ has no member named ‘on’.

    error: ‘class WiFiServer’ has no member named ‘serveStatic’.

    Do you have any idea how can I solve them?

    Thank you.

    Reply
    • Hi.
      Are you sure you installed the libraries?
      Do you have more than one Arduino IDE installed on your computer?
      Sometimes, multiple installations may conflict with the libraries.
      Regards,
      Sara

      Reply
    • Solución forum.arduino.cc/index.php?topic=645886.0

      “he3117 Re: ESP32s no puede detectar / montar la tarjeta microSD # 3
      11 de mayo de 2020 13:54
      Para cualquier otra persona que tenga el mismo problema con el módulo micro SD, debe conectar el pin VCC del módulo de la tarjeta micro SD al pin Vin de ESP32, no a la salida de 3.3 V.”

      Reply
      • Hi.
        Thanks for sharing.
        But, take into account that it will depend on the microSD card module you’re using.
        If you’re using one exactly like ours, you should only feed 3.3V.
        Regards,
        Sara

        Reply
    • Hi.
      This is the code provided by the library.

      server.onNotFound([](AsyncWebServerRequest *request){
      request->send(404);
      });

      Instead of sending 404, I think you can use the “regular” commands to send a customized page.

      Regards,
      Sara

      Reply
  7. Hi Sara,

    Yes, I know the library calls, but it seems like there is no library overload of send() that takes a statuscode and a filename as input.

    I can send a 404 statuscode like:
    request->send(404);
    or
    request->send(404, “text/html”, “”);

    Likewise, I can send a page stored on SDcard like:
    request->send(SD, “”, “text/html”);
    but this always send status code 200 (OK) to the client.

    I am looking for something like:
    request->send(404, SD, “”, “text/html”);
    to send a 404 (NOTFOUND) status with a page_on_SD as content.

    Thanks for thinking with me!

    Regards,
    Marcel

    Reply
  8. (strings were deleted from my post because I embedded them within less-than and greater-than. Let’s try again)

    Hi Sara,

    Yes, I know the library calls, but it seems like there is no library overload of send() that takes a statuscode and a filename as input.

    I can send a 404 statuscode like:
    request->send(404);
    or
    request->send(404, “text/html”, “HTMLsourceAsString”);

    Likewise, I can send a page stored on SDcard like:
    request->send(SD, “FileNameAsString”, “text/html”);
    but this always send status code 200 (OK) to the client.

    I am looking for something like:
    request->send(404, SD, “FileNameAsString”, “text/html”);
    to send a 404 (NOTFOUND) status with a page_on_SD as content.

    Thanks for thinking with me!

    Regards,
    Marcel

    Reply
  9. Good afternoon, I’m trying to find a way to download a csv file from the SD, through the browser, do you have an idea of ​​how to do it? I tried that way, but it doesn’t.
    request->send(SD, “/datalog.csv”, “text/text”);

    Reply
  10. I want to ask, why when i tried to upload the source code its always say “Error compiling for board ESP32 Dev Module” is there any error on my Arduino IDE?

    Reply
    • Hi.
      First, check that you have the right board selected in Tools > Boards.
      Then, when it throws that errors, it highlights the line that is giving problems. What’s the line that you have highlighted?
      Regards,
      Sara

      Reply
        • Hi. Make sure that you’ve saved all the needed files to build the web server on the micro SD card.
          Additionally, make sure you’ve inserted your network credentials in the ssid and password variables.
          Regards,
          Sara

          Reply
    • Hi.
      Our microSD card module works well with 3.3V.
      Other microSD card modules might need a different voltage.
      Regards,
      Sara

      Reply
  11. Hi, Rui and Sara. Great tutorial. I tried to combine what I learn from several of your tutorial with a bit of success. I written a code to read a float sensors which is place at different water level and show the result/msg (water level) on the web page. I was able to do it. But my problem is I had to refresh the web page for it to update the current water level. I couldn’t figure out what line of code is missing for it to do so. My code doesn’t have any output to control. Thank You

    Reply

Leave a Reply to Jason Cancel reply

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.