我使用的是esp32cam模块和sdcard接口。我能够保存在sdcard中的图像。此图像在Windows中打开。接下来,我要添加http_server,并在html页面中访问sdcard中的图像,并在img标记的sdcard中使用。但是html不显示图像,在teraterm日志中它说它找不到文件。
httpd_uri: httpd_uri: URI '/sdcard/fnb1.jpg' not found为html请求提供服务的代码如下:
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 }在line#6这里
strcat(ret_homepage,"<img src=\"/sdcard/fnb1.jpg\" width=\"500\" height=\"600\">");http_server似乎无法访问mount_point "/sdcard“,因此无法访问fbn1.jpg。
我所做的SD卡安装如下所示。此挂载工作良好,因为所编写的文件可从windows读取。下一件事是为什么上面的一行不读呢?它可能需要注册到虚拟文件系统(VFS)!如果是这样的话,那么在"esp_vfs_fat_sdspi_mount“之后,line#37需要做"esp_vfs_fat_register”才能工作吗?这里有谁能给我建议吗?
#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 }发布于 2022-01-23 20:22:47
在做任何事情之前,你需要了解你在做什么。
您正在使用ESP32。你查过它的文档了吗?它甚至有一个示例程序。
现在,您已经为某些URI注册了一个处理程序。它看起来可能是这样的?:) (或者您更改了uri)。
static const httpd_uri_t hello = {
.uri = "/hello",
.method = HTTP_GET,
.handler = hello_get_handler,
/* Let's pass response string in user
* context to demonstrate it's usage */
.user_ctx = NULL
};
...
httpd_register_uri_handler(server, &hello);这意味着,如果服务器收到HTTP获取请求 for /hello,则程序调用hello_get_handler(),后者将使用您在处理程序中编写的HTML进行响应。
HTML文档都在那里。浏览器只接收您发送的文本,仅此而已。请参阅浏览器中的源代码。换句话说,在这个时候(或者永远),src=\"/sdcard/fnb1.jpg\"不会被图像所取代。
<img>标记/元素仅仅是浏览器用给定参数显示'src‘指向的资源的指令。“src”甚至可以是另一台服务器上的资源,例如:
<img src=\"http://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg\">(尝试使用图像的已知地址。)例外情况:图像也可以是整个图像文件的Base64编码字符串。但是,它不能是实际文件本身,即jpeg作为二进制blob。如果您真的想将图像嵌入到文档中,可以使用Base64方法,但这不是您在这里所要做的。
所以要重申的是,图像本身并不是在这里传输的。只有描述图像元素的HTML代码。纯文字。
浏览器将为图像资源本身发出单独的HTTP请求。您已经定义了一个相对URI,因此浏览器尝试从<your_server>/sdcard/fnb1.jpg获取它。
您的代码没有能够响应GET的处理程序,因此不会显示图像。
因此,让我们再一次假设您的ESP32获得IP 192.168.1.42,这基本上就是所发生的事情:

因此,您需要做的是实现和注册另一个句柄,它也可以为映像服务。此时,它可以是专门处理一个映像的处理程序。只需编写一些URI并将其嵌入到<img>中即可。当然,URI可以保持为/sdcard/fnb1.jpg --这并不重要。只需了解这是HTTP服务器中的URI。它与SD卡中图像的文件系统路径一点关系都没有。
响应HTTP 200 OK响应,至少使用标题‘content: image/jpeg’。根据文档 of httpd_resp_send
..。如果没有设置状态代码和内容类型,默认情况下这将发送200个OK状态代码和内容类型作为text/html。..。httpd_resp_set_type() -用于设置内容类型.
因此,只有内容类型需要由您设置("image/jpeg")。
再次:您需要定义一个响应处理程序,它可以处理对图像的GET请求。至少它可以是一个特定图像的硬编码URI。在处理程序中,需要使用httpd_resp_send从SD卡(或其他地方)发送文件,并将内容类型标头设置为带有httpd_resp_set_type的"image/jpeg"。所以,就像:
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;
}https://stackoverflow.com/questions/70819297
复制相似问题