WebViewer html file with image stored in SD card?

Hi people,
I'd like to know if it is possible to visualize an image (currently stored in the ESP32-Cam's board SD card) using an html file to load in a WebViewer. In my app I have the following block that do this type of things but on a streaming html channel. Please, can someone help? Thanks

As you have shown, you can use the "data:text/html," approach with image files that are being served via http. If the image files are "local" files, then you will need to create a physical html file in the same location as the image files, and call that to the webviewer. You can use the webviewstring to set a chosen image file.

It might be too difficult to do this on the ESP32's sd card, therefore you may have to trasnfer the image files to the device (phone) to do this.

There may be other ways, others will be along...

Thanks Tima2,
yes, the 'simple' way should be this endeed (I'm not an expert, I found a couple of ways to try file transfer from ESP32's SD card to phone but without success). In fact it's not hard to save an html file in this remote SD card that point out to a choosen already exisiting image file. My problem is how to set the ReadFrom file call in the File component to point that html file on SD.



Sorry, I didn't explain it clearly. The SD card where images are stored, is the internal ESP32-Cam's board one. This ESP32 board communicates with the phone App via WiFi as http server.

Ah, if it it serving http, then why not use it in the same way as your http example ? ....


or for that matter an http url for your image from the ESP32 http server?

Ah, yes, sorry, my fault ... I'm a newbie.
I suppose it is sufficient to add an http_handler in the Camera server definiton (see below, part of Arduino code for the ESP32-Cam) to an html file with the image src properly defined for my image file in it ...

// CAMERA SERVER #######################################################################
void startCameraServer(){
httpd_config_t config = HTTPD_DEFAULT_CONFIG();

    httpd_uri_t status_uri = {
        .uri       = "/status",
        .method    = HTTP_GET,
        .handler   = status_handler,
        .user_ctx  = NULL

    httpd_uri_t cmd_uri = {
        .uri       = "/control",
        .method    = HTTP_GET,
        .handler   = cmd_handler,
        .user_ctx  = NULL

    httpd_uri_t capture_uri = {
        .uri       = "/capture",
        .method    = HTTP_GET,
        .handler   = capture_handler,
        .user_ctx  = NULL

	httpd_uri_t stream_uri = {
        .uri       = "/stream",
        .method    = HTTP_GET,
        .handler   = stream_handler,
        .user_ctx  = NULL

	httpd_uri_t image_uri = {
        .uri       = "/image",
        .method    = HTTP_GET,
        .handler   = sdimage_handler,
        .user_ctx  = NULL

I have not done this tutorial, maybe you can get some ideas.

In this topic

Web Server with Images stored in SdCard.

I'm using Espressif esp32 library. My app work in progress but it is already able to streaming real-time on a WebViewer, capture and save jpegs on SPIFFS as well as SD (SD_MMC lib), list, rename or delete those files in SD. Now I'd like to be able to choose a jpeg from the SD list (not an issue) and visualize it on my phone.
I tried to add ESPAsyncWebServer in order to include a WebServer for streamFile() call

#include <ESPAsyncWebServer.h>

but there are incompatibilties with esp32 lib:

In file included from /home/gigi/Documents/ESP32-Cam-GG/ESP32-Cam-GG.ino:24:0:
/home/gigi/Arduino/libraries/ESPAsyncWebServer/src/ESPAsyncWebServer.h:62:18: error: redeclaration of 'HTTP_GET'
   HTTP_GET     = 0b00000001,
In file included from /home/gigi/.arduino15/packages/esp32/hardware/esp32/1.0.4/tools/sdk/include/esp_http_server/esp_http_server.h:22:0,
                 from /home/gigi/Documents/ESP32-Cam-GG/ESP32-Cam-GG.ino:6:

#include "esp_camera.h"
#include "esp_timer.h"
#include "esp_http_server.h"
#include "img_converters.h"
#include "Arduino.h"
#include "fb_gfx.h"
#include "fd_forward.h"
#include "fr_forward.h"
#include "FS.h"					// SD/SPIFFS ESP32
#include "SD_MMC.h"				// SD ESP32
#include "soc/soc.h"			// brownout problems
#include "soc/rtc_cntl_reg.h"	// brownout problems
#include <WiFi.h>
#include <SPIFFS.h>

Here is my actual Camera server code (source esp32 lib examples)):

void startCameraServer(){
httpd_config_t config = HTTPD_DEFAULT_CONFIG();

httpd_uri_t status_uri = {
    .uri       = "/status",
    .method    = HTTP_GET,
    .handler   = status_handler,
    .user_ctx  = NULL

httpd_uri_t cmd_uri = {
    .uri       = "/control",
    .method    = HTTP_GET,
    .handler   = cmd_handler,
    .user_ctx  = NULL

httpd_uri_t capture_uri = {
    .uri       = "/capture",
    .method    = HTTP_GET,
    .handler   = capture_handler,
    .user_ctx  = NULL

httpd_uri_t stream_uri = {
.uri = "/stream",
.method = HTTP_GET,
.handler = stream_handler,
.user_ctx = NULL

ra_filter_init(&ra_filter, 20);

mtmn_config.min_face = 80;
mtmn_config.pyramid = 0.7;
mtmn_config.p_threshold.score = 0.6;
mtmn_config.p_threshold.nms = 0.7;
mtmn_config.r_threshold.score = 0.7;
mtmn_config.r_threshold.nms = 0.7;
mtmn_config.r_threshold.candidate_number = 4;
mtmn_config.o_threshold.score = 0.7;
mtmn_config.o_threshold.nms = 0.4;
mtmn_config.o_threshold.candidate_number = 1;


Serial.printf("Starting web server on port: '%d'\n", config.server_port);
if (httpd_start(&camera_httpd, &config) == ESP_OK) {
    httpd_register_uri_handler(camera_httpd, &cmd_uri);
    httpd_register_uri_handler(camera_httpd, &status_uri);
    httpd_register_uri_handler(camera_httpd, &capture_uri);
    httpd_register_uri_handler(camera_httpd, &image_uri);
    httpd_register_uri_handler(camera_httpd, &file_download);

config.server_port += 1;
config.ctrl_port += 1;
Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
    httpd_register_uri_handler(stream_httpd, &stream_uri);


how can I share my App Inventor project to anyone interested here?

You can upload files to this topic.

I found an http handler to send files here.
Tested on my code with:

esp_err_t file_get_handler(httpd_req_t *req) {
	FILE* file;
	char *file_buf;
	size_t bytes_read;
	unsigned int file_size = 0;
	char cont_len[8];
	file = fopen("/spiffs/photoSPIFFS.jpg", "r");
	if(file != NULL) {
		fseek(file, 0, SEEK_END);
		file_size = ftell(file);
		fseek(file, 0, SEEK_SET);
		sprintf(cont_len, "%d", file_size);
		Serial.printf("File open \"/spiffs/photoSPIFFS.jpg\". File size: %d Bytes\n", file_size);
		Serial.printf("content-length %s\n", cont_len);
		file_buf = (char *)malloc(file_size);
		if (file_buf == NULL) {
			Serial.println("Failed to allocate memory");
		    return ESP_FAIL;
		bytes_read = fread(file_buf, 1, file_size, file);
        ESP_LOGI("MESSAGE","%s", file_buf);
		httpd_resp_set_type(req, "text/plain");
		httpd_resp_set_hdr(req, "Content-Length", cont_len);
		httpd_resp_set_hdr(req, "Host", "ESP32");
		ESP_ERROR_CHECK(httpd_resp_send(req, file_buf, sizeof(file_buf)));
		ESP_LOGI("SPIFFS", "Data sent: %d Bytes", bytes_read);
		Serial.printf("Data sent: %d Bytes\n", bytes_read);
	} else {
		ESP_LOGE("SPIFFS", "Failed to open file for sending");
		Serial.println("Failed to open file for sending");
	return ESP_OK;

This could be a valid solution. My idea is to write a sequence where the choosen SD image file is copied to SPIFFS as photoSPIFFS.jpg, then send this image file to phone's App.
The output on the Arduino serial monitor obtained by the above code is:

File open "/spiffs/photoSPIFFS.jpg". File size: 14539 Bytes
content-length 14539
Data sent: 14539 Bytes

So, the file seems to be correctly sent. My problem now is, if it is possible, how to show this image file on App Inventor?
In App I have a Web component waiting for incoming http responses:

And this is an example of a function that do something on the ESP32 and send an http response (p is a pointer to a text message)

void savePhotoInSPIFFS() {
	camera_fb_t * fb = NULL; // pointer
	bool ok = 0; // Boolean indicating if the picture has been taken correctly
	do {
		// Serial.println("Taking a photo...");
		fb = esp_camera_fb_get();
		if (!fb) {
			Serial.println("Camera capture failed in SPIFFS");
			p+=sprintf(p, "Camera capture failed in SPIFFS<br>");
		// Serial.printf("Picture file name: %s\n", SPIFFS_PHOTO_FILE_NAME);
		// Insert the data in the photo file
		if (!file) {
			Serial.println("Failed to open SPIFFS file in writing mode");
			p+=sprintf(p, "Failed to open SPIFFS file in writing mode<br>");
		} else {
			file.write(fb->buf, fb->len); // payload (image), payload length
			// Serial.print("The picture has been saved in SPIFFS: ");
			// Serial.print(SPIFFS_PHOTO_FILE_NAME);
			// Serial.print(" - Size: ");
			// Serial.print(file.size());
			// Serial.println(" bytes");
			p+=sprintf(p, "SPIFFSsaved"); // NON CAMBIARE IL MESSAGGIO!!!!
		ok = checkSPIFFSphoto(SPIFFS);
	} while (!ok);

Excuse me! Can anyone tell me what extension is this?


This is just a procedure with one parameter ip


Thank you so much.
Actually I was trying to get some confirmation via
httpd_resp_set_hdr(req, confirmation, sizeOf(confirmation));

Where if I changed any settings of the camera I would receive a message like "Brightness: 45" in my MIT application.

Can you please help me to know how to do so?