ESP32 HTTP web server: serving image from file system

In this tutorial we will check how to serve an image from the ESP32 file system to a HTTP client. The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.


Introduction

In this tutorial we will check how to serve an image from the ESP32 file system to a HTTP client. We will use the HTTP async web server libraries in order to setup the server and we will use the ESP32 SPIFFS file system.

From a previous tutorial on how to serve HTML from the file system with the HTTP async web server libraries, please check here.

The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.


Uploading the image

Before starting to code and uploading the program to the ESP32, we will need to upload the image to the file system. In order to do so, we will use this Arduino IDE plugin, which allows to upload files to the ESP32 SPIFFS file system from a folder in a computer.

For a detailed tutorial on the procedure, please check this previous post, which contains step by step instructions with images.

As a short summary, after installing the mentioned plugin, we need to create a new Arduino sketch, save it and, on the sketch folder, create a new folder called “data“. In that folder, we should put the image, like shown in figure 1.

ESP32 upload image to SPIFFS.png

Figure 1 – Putting the image in the “data” folder.

Note that we need to be careful regarding the file name and extension, since they will compose the name of the file that will be uploaded to the SPIFFS file system of the ESP32.

For example, I’m using an image that is listed as JPEG, but the actual file has a .jpg extension, and thus we will need to look for a file named “test.jpg” in the ESP32 code.

The easiest way to confirm the correct file name is navigating to the “data” folder using the command line of your operating system and listing the files of that folder. Figure 2 shows this on Windows and, as can be seen, the file is listed with the .jpg extension.

JPEG fle listed in windows file system

Figure 2 – Image listed in Windows file system.

Note that the size of the SPIFFS file system is limited, so you should not upload images too big. Even if the image doesn’t exceed the maximum size allowed for a file, the HTTP web framework may not work well with very large files, although I haven’t yet tested for these scenarios. Nonetheless, I have tested with images around 20 KB and everything worked fine.

For reference, below you can see the image I have used for the test shown in this tutorial.

test.jpg

Figure 3 – Image used in the tests.

To finalize, go back to the Arduino IDE and, on the “tools” menu, click the ESP32 Sketch Data Upload menu item. Wait for the procedure to finish and, after that, the image should be in the file system of the device.

Take in consideration that the file will be created in the root directory of the SPIFFS file system, so its full path will be “/test.jpg“. In order to confirm if it was correctly created in the file system, you can follow this tutorial to fetch the file size, thus confirming that the file was indeed created.


The code

We will start our code by doing all the necessary library includes. In order to connect the ESP32 to a WiFi network, we need the WiFi.h library. To be able to setup the async HTTP web server, we will also need the ESPAsyncWebServer.h library.

Finally, we will need the SPIFFS.h library, since we are going to interact with the file system in order to retrieve the image.

Following the usual procedure when setting up a web server on the ESP32, we need to declare the WiFi credentials so we can connect the device to the network.

We will also need an object of class AsyncWebServer, which we will be using to setup the routes of the server. Remember from previous posts that the constructor for this class will receive as input the number of the port where the server will be listening to incoming HTTP requests.

#include "WiFi.h"
#include "SPIFFS.h"
#include "ESPAsyncWebServer.h"

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

AsyncWebServer server(80);

Moving on to the Arduino setup function, we will start by opening a serial connection to output some content from our program.

Next, we will mount the SPIFFS file system, so we can later access the image we are going to serve to the client. We do this by calling the begin method on the SPIFFS extern variable, which becomes available after importing the SPIFFS.h library.

Remember from the previous post that we can pass a Boolean value indicating if we want the file system to be formatted in case mounting fails. In our case we don’t want this to happen because if we format the file system, then our image will be lost. So, if an error occurs while mounting, then the best approach is to re-upload the file.

Taking this in consideration, we don’t need to pass any value as input of the begin method since the mentioned formatting Boolean value will default to false.

Serial.begin(115200);

if(!SPIFFS.begin()){
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
}

Moving on, we will connect the ESP32 to the WiFi network and print the local IP assign to the device after the procedure finishes. This IP will be needed by the client that will reach the server.

while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
}

Serial.println(WiFi.localIP());

Now we will take care of setting up the route that will be serving the image. As we have been doing in all the previous tutorials, we do this by calling the on method on the AsyncWebServer object.

As first input of the method, we will pass a string with the route, which will be “/img” for this example. You can use other route if you want, as long as you use that one when accessing the server.

As second parameter we will specify the HTTP methods allowed. We will only listen to HTTP GET requests in this route.

Finally, as third parameter, we will specify the route handling function, which will be executed when a request is made.

Our handling function will correspond to sending the image back to the client as answer to the HTTP GET request. To do it, we simply need to call the send method on the AsyncWebServerRequest object pointer that is passed by the HTTP web server framework to our handling function.

Note that the send method is overloaded and it has many formats that we can use. In our case, we will use the format that receives as input an object of class FS (from File System), as second a path to a file in the file system, and as third the content-type of the response.

The SPIFFS extern variable that we use to interact with the file system is of class SPIFFSFS, which inherits from the FS class, which means we can use it as first input of the send method.

As second input we will pass string “/test.jpg”, which is the path of the image we uploaded to the file system. Finally, we will set the content-type to “image/jpeg”, so the browser knows how to correctly interpret the content we are going to return.

server.on("/img", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(SPIFFS, "/test.jpg", "image/jpeg");
});

The final source code can be seen below. It already includes a call to the begin method on our AsyncWebServer object, so it starts listening to incoming requests. Note also that we left the main loop empty since the server works asynchronously, which means we don’t need to periodically poll it for clients.

#include "WiFi.h"
#include "SPIFFS.h"
#include "ESPAsyncWebServer.h"

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

AsyncWebServer server(80);

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

  if(!SPIFFS.begin()){
        Serial.println("An Error has occurred while mounting SPIFFS");
        return;
  }

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println(WiFi.localIP());

  server.on("/img", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/test.jpg", "image/jpeg");
  });

  server.begin();
}

void loop(){}


Testing the code

To test the code, simply compile it and upload it to your ESP32 device using the Arduino IDE. Once the procedure finishes, open the Arduino IDE serial monitor and wait for the the local IP assigned to the ESP32 to be printed, which will happen then the device connects to the WiFi network successfully. Copy that IP address.

Next, open a web browser of your choice and access the following URL, changing #yourIP# by the IP you have just copied:

http://#yourIP#/img

The image previously uploaded to the file system should be returned to the browser, like shown in figure 4.

ESP32 Arduino web server image from file system.png

Figure 4 – Image from the ESP32 file system returned to the client.

 

Related Posts

Advertisements

3 Replies to “ESP32 HTTP web server: serving image from file system”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s