I am using esp32cam module with sdcard interface. The image I am able to save in the sdcard. This image opens in Windows PC. Next thing, I have done is to add http_server and in the html page I wanted to access the image from sdcard and using in src attrtibute of img tag. But the html does not display image and in the teraterm log it says it cannot find the file.
httpd_uri: httpd_uri: URI '/sdcard/fnb1.jpg' not found
The code to serve the html request is as follows:
1 static esp_err_t hello_get_handler(httpd_req_t *req) {
2 strcpy(ret_homepage,"<!DOCTYPE html><html><head><title>SwitchControl</title>");
3 strcat(ret_homepage, "</head><body>");
4 strcat(ret_homepage, "<div>");
5 strcat(ret_homepage, "Picture1:");
6 strcat(ret_homepage,"<img src=\"/sdcard/fnb1.jpg\" width=\"500\" height=\"600\">");
7 strcat(ret_homepage, "</div>");
8
9 strcat(ret_homepage, "</body>");
10 strcat(ret_homepage, "</html>");
11
12 /* Set some custom headers */
13 httpd_resp_set_hdr(req, "Connection", "close");
14 httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
15
16 /* Send response with custom headers and body set as the
17 * string passed in user context*/
18 const char *resp_str = (const char*) ret_homepage;
19
20 httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
21
22 ESP_LOGI(TAG, "Response sent for home page request.Time:%s",esp_log_system_timestamp());
23
24 return ESP_OK;
25 }
Here at the line#6
strcat(ret_homepage,"<img src=\"/sdcard/fnb1.jpg\" width=\"500\" height=\"600\">");
the http_server seems not able to access the mount_point "/sdcard" and consequently not able to access fbn1.jpg.
The mount of SD Card I have done like below. This mount is working fine as the file written is readable from windows PC. Next thing is why the above line does not read it? Probably it needs to do register to Virtual File System (VFS)! If so, then after "esp_vfs_fat_sdspi_mount", line#37 do I have to do "esp_vfs_fat_register" to make it work? Can anyone advice here please?
#define MOUNT_POINT "/sdcard"
....
1 void mount_sdcard(){
2 esp_err_t ret;
3 esp_vfs_fat_sdmmc_mount_config_t mount_config = {
4 #ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
5 .format_if_mount_failed = true,
6 #else
7 .format_if_mount_failed = false,
8 #endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
9 .max_files = 5, .allocation_unit_size = 16 * 1024
10 };
11 sdmmc_card_t* card;
12 const char mount_point[] = MOUNT_POINT;
13 ESP_LOGI(TAG, "Initializing SD card");
14 #ifndef USE_SPI_MODE
15 ESP_LOGI(TAG, "Using SDMMC peripheral");
16 sdmmc_host_t host = SDMMC_HOST_DEFAULT();
17 sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
18
19 // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups.
20 gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
21 //... omitted for brevity
22 gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes
23 ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
24 #else
25 ESP_LOGI(TAG, "Using SPI peripheral");
26
27 sdmmc_host_t host = SDSPI_HOST_DEFAULT();
28 spi_bus_config_t bus_cfg = { .mosi_io_num = PIN_NUM_MOSI,.miso_io_num = PIN_NUM_MISO,.sclk_io_num = PIN_NUM_CLK,.quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = 4000, };
29 ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CHAN);
30 if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize bus.");return; }
31
32 // This initializes the slot without card detect (CD) and write protect (WP) signals.
33 // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
34 sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
35 slot_config.gpio_cs = PIN_NUM_CS;slot_config.host_id = host.slot;
36
37 ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
38 #endif //USE_SPI_MODE
39
40 if (ret != ESP_OK) { //...
41 return;
42 }
43
44 // Card has been initialized, print its properties
45 sdmmc_card_print_info(stdout, card);
46 }
CodePudding user response:
You need to understand what you are doing before doing anything.
You are using the ESP32 HTTP Server API. Have you checked its 
So what you need to do is implement and register another handle that can serve the image as well. At this point it can be a handler that handlers the one image specifically. Just make up some URI and embed it to your <img>. The URI can of course remain as /sdcard/fnb1.jpg - it doesn't matter. Just understand that this is the URI in your HTTP server. It has no relation at all to the filesystem path for your image in the SD card.
Respond with a HTTP 200 OK response, with at least the header 'content-type: image/jpeg'. As per the documentation of httpd_resp_send:
... If no status code and content-type were set, by default this will send 200 OK status code and content type as text/html. ... httpd_resp_set_type() - for setting the Content Type ...
So only the content type needs to be set by you ("image/jpeg").
Once again: You need to define a response handler that can handle the GET request to your image. At minimum it can be a hardcoded URI to the one specific image. In the handler you need to use httpd_resp_send to send the file from the SD card (or wherever) and set the content-type header to be "image/jpeg" with httpd_resp_set_type. So something like:
static const httpd_uri_t img_example = {
.uri = "/img/example.jpg",
.method = HTTP_GET,
.handler = img_example_get_handler,
.user_ctx = NULL
};
static esp_err_t img_example_get_handler(httpd_req_t *req)
{
// 1. get a pointer to your image file
// 2. httpd_resp_set_type to set the correct content type header
// esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type)
// Parameters
// [in] r: The request being responded to
// [in] type: The Content Type of the response
// 3. httpd_resp_send to send the response, with the image file as buf
// esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len)
// Parameters
// [in] r: The request being responded to
// [in] buf: Buffer from where the content is to be fetched
// [in] buf_len: Length of the buffer, HTTPD_RESP_USE_STRLEN to use strlen()
return ESP_OK;
}
