ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统
ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统
概述
在前述章节我们讲述了在网页端控制多个 GPIO 的案例。当程序开始变得复杂,让一些功能“自动起来”是一个好的选择。
在前面的示例中,我们需要在后端为每个前端代码的 URL 指定一个对应的 handler,在 URL 变的越来越多的情况下,这种处理将变的不那么方便。
此外,随着系统功能越来越多,前端设计中使用的 HTML文件、CSS 文件、JS 文件越来越多,如果系统能自动管理、加载对应的文件,将对项目的设计与维护是很大的改善。
本节开始,我们将在后端代码中使用文件系统,默认使用 ESP-IDF 提供的 SPIFFS 文件系统,读者也可以使用更为通用的 Fatfs 文件系统,本质上两者是等价的。
需求及功能解析
功能还是上节讲述的在网页控制一个 LED 灯的亮灭。
本节演示如何通过文件系统来保存前端(HTML、CSS、JS 文件)所需要的内容,并在后端系统中需要指定的文件时实现自动索引到 SPIFFS 文件系统中对应的前端文件。

示例解析
目录结构
├── CMakeLists.txt
├── main
│ ├── CMakeLists.txt
│ └── main.c User application
├── components
│ └── fs_image└── web_image└── index.html└── CSS└── JS└── CMakeLists.txt
└── README.md This is the file you are currently reading
-
目录结构主要包含主目录 main,以及组件目录 components.
-
其中组件目录components中包含了用于存储网页文件的 fs_image 目录(即前述前端文件),fs_image 目录下的 web_image 是文件系统中的内容。IDF 中通过 CMakeLists.txt 中指定的语句,将 web_image 中的内容,按照相同的目录结构写入到 ESP32 的 flash 存储器中:
set(WEB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/web_image") if (EXISTS ${WEB_SRC_DIR})spiffs_create_partition_image(fs ${WEB_SRC_DIR} FLASH_IN_PROJECT) else()message(FATAL_ERROR "${WEB_SRC_DIR} doesn't exit.") endif()
前端代码
前端代码与上节的内容一致,只是存储目录更加规范,HTML、CSS、JS 分别是不同的文件:

此外,在 HTML 中对于需要的 CSS 文件、JS 文件,分别使用 href 、 src 指定对应文件在文件系统中的存储位置:
<link rel="stylesheet" type="text/css" href="css/stylesheet.css">
<script src="js/script.js"></script>
后端代码
后端代码中主要是增加了文件系统的初始化,以及自动在文件系统中查找需要的文件的 handler。
1)增加文件系统的初始化:
/* Start the server for the first time */
ESP_ERROR_CHECK(init_fs());
2)在文件系统中增加查找文件的 handler:
httpd_uri_t httpd_uri_array[] = {{"/states", HTTP_GET, output_states_get_handler, rest_context},{"/update", HTTP_GET, update_state_get_handler, rest_context},{"/*", HTTP_GET, rest_common_get_handler,rest_context}//Catch-all callback function for the filesystem, this must be set to the array last one};
其中 “/states”、“/update” 分别是查询当前 GPIO 状态、更新 GPIO 状态的 ULR。
新增的 “/*” 是一个通配符,必须放在httpd_uri_array[] 的最后一个,代表上述所有未匹配到的 URL,都去这个通配符对应的 handler 里去查找对应的文件,获取对应的数据。这就是在文件系统中自动查找对应文件的关键处理函数。
当使用浏览器访问对应的 URL 时,会请求对应的文件,ESP32 将在 rest_common_get_handler() 中根据 URL 中指定的文件信息查找存储在 ESP32 SPIFFS 文件系统中的内容。
示例效果

讨论
1)前端代码与后端代码是有对应关系的,本示例中前端发出的 URL 中通过 ? 识别请求的文件名称,因此后端代码中有:
char* p = strrchr(filepath, '?');if (p != NULL) {*p = '\0';}int fd = open(filepath, O_RDONLY, 0);
2)不同的文件有不同的发送类型符号,本例中通过文件的后缀名,自动识别要打开的文件,并设置对应的文件类型描述符号:
/* Set HTTP response content type according to file extension */
static esp_err_t set_content_type_from_file(httpd_req_t* req, const char* filepath)
{const char* type = "text/plain";if (CHECK_FILE_EXTENSION(filepath, ".html")) {type = "text/html";} else if (CHECK_FILE_EXTENSION(filepath, ".js")) {type = "application/javascript";} else if (CHECK_FILE_EXTENSION(filepath, ".css")) {type = "text/css";} else if (CHECK_FILE_EXTENSION(filepath, ".png")) {type = "image/png";} else if (CHECK_FILE_EXTENSION(filepath, ".ico")) {type = "image/x-icon";} else if (CHECK_FILE_EXTENSION(filepath, ".svg")) {type = "text/xml";}return httpd_resp_set_type(req, type);
}
3)注意初始化 web 时,其文件系统的地址,要和实际使用的 spiffs mount 的 路径 web_base_point 要一致,否则会无法正确找到对应的文件:
server = start_webserver(web_base_point);
esp_err_t init_fs(void)
{esp_vfs_spiffs_conf_t conf = {.base_path = web_base_point,.partition_label = NULL,.max_files = 5,//maybe the num can be set smaller.format_if_mount_failed = false};...
}
总结
1)本节主要是介绍通过文件系统保存 ESP32 Web 的前端文件,然后在后端代码中引入 SPIFFS 文件系统。
2)通过在后端代码中新增 “/*” 通配符,实现所有未匹配到的 URL,都自动地去这个通配符对应的 handler 里去查找对应的文件,获取对应的数据。
资源链接
1)ESP32-Web-Server ESP-IDF系列博客介绍
2)对应示例的 code 链接 (点击直达代码仓库)
3)下一篇:ESP32-Web-Server 实战编程- 使用 AJAX 自动更新网页内容
(码字不易感谢点赞或收藏)
相关文章:
ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统
ESP32-Web-Server 实战编程-使用文件系统建立强大的 web 系统 概述 在前述章节我们讲述了在网页端控制多个 GPIO 的案例。当程序开始变得复杂,让一些功能“自动起来”是一个好的选择。 在前面的示例中,我们需要在后端为每个前端代码的 URL 指定一个对…...
kubeadm快速搭建k8s高可用集群
1.安装及优化 1.1基本环境配置 1.环境介绍 (1).高可用集群规划 主机名ip地址说明k8s-master01192.168.2.96master节点k8s-master02192.168.2.97master节点k8s-master03192.168.2.98master节点k8s-node01192.168.2.99node节点k8s-node02192.168.2.100n…...
GoLong的学习之路,进阶,Redis
这个redis和上篇rabbitMQ一样,在之前我用Java从原理上进行了剖析,这里呢,我做项目的时候,也需要用到redis,所以这里也将去从怎么用的角度去写这篇文章。 文章目录 安装redis以及原理redis概念redis的应用场景有很多red…...
Linux重置MySql密码(简洁版)
关闭验证 /etc/my.cnf-->[mysqld]-->skip-grant-tables 重启MySql service mysql restart 登陆MySql mysql -u root 刷新权限 FLUSH PRIVILEGES; 更新密码 ALTER USER rootlocalhost IDENTIFIED BY 123456; 退出MySql exit 打开验证 /etc/my.cnf-->[mysqld]-->skip…...
Ubuntu部署jmeter与ant
为了整合接口自动化的持续集成工具,我将jmeter与ant都部署在了Jenkins容器中,并配置了build.xml 一、ubuntu部署jdk 1:先下载jdk-8u74-linux-x64.tar.gz,上传到服务器,这里上传文件用到了ubuntu 下的 lrzsz。 ubunt…...
如何使用 RestTemplate 进行 Spring Boot 微服务通信示例?
在 Spring Boot 微服务架构中,RestTemplate 是一个强大的工具,用于简化微服务之间的通信。下面是一个简单的示例,演示如何使用 RestTemplate 进行微服务之间的 HTTP 通信。 首先,确保你的 Spring Boot 项目中已经添加了 spring-b…...
新开普掌上校园服务管理平台service.action RCE漏洞复现 [附POC]
文章目录 新开普掌上校园服务管理平台service.action RCE漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 新开普掌上校园服务管理平台service.action RCE漏洞复现 [附POC] 0x01 前言 免责声明:请勿…...
滤波器、卷积核与内核的关系
上来先总结举例子解释 上来先总结 内核(kernel)是一个二维矩阵,长*宽;滤波器(filter)也叫卷积核,过滤器。是一个三维立方体,长 宽 深度, 其中深度便是由多少张内核构成…...
沉默是金,寡言为贵
佛说:“人受一句话,佛受一柱香。”佛教的十善,其中有关口德就占了四样:恶口、妄语、两舌、绮语,可见口德是很重要的。言为心声,能说出真心的话,必然好听;假如说话言不由衷&#x…...
【网络奇遇之旅】:那年我与计算机网络的初相遇
🎥 屿小夏 : 个人主页 🔥个人专栏 : 计算机网络 🌄 莫道桑榆晚,为霞尚满天! 文章目录 一. 前言二. 计算机网络的定义三. 计算机网络的功能3.1 资源共享3.2 通信功能3.3 其他功能 四. 计算机网络…...
量化误差的测量
因为转换的精度有限,所以将模拟值数字化时会不可避免地出现量化误差。量化误差由转换器及其误差、噪声和非线性度决定。当输入信号和计数器时基有区别时就会产生量化误差。根据输入信号的相位和计数器时基的匹配程度,计数器有下列三种可能性:…...
8年测试工程师分享,我是怎么开展性能测试的(基础篇)
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...
微服务API网关Spring Cloud Gateway实战
概述 微服务网关是为了给不同的微服务提供统一的前置功能;网关服务可以配置集群,以承载更多的流量;负载均衡与网关互相成就,一般使用负载均衡(例如 nginx)作为总入口,然后将流量分发到多个网关…...
uniapp打包ios有时间 uniapp打包次数
我们经常用的解决方案有,分包,将图片上传到服务器上,减少插件引入。但是还有一个方案好多刚入门uniapp的人都给忽略了,就是在源码视图中配置,开启分包优化。 1.分包 目前微信小程序可以分8个包,每个包的最大存储是2M,也就是说你文件总体的大小不能超过16M,每个包的大…...
【笔记+代码】JDK动态代理理解
代码地址 https://github.com/cmdch2017/JDKproxy.git/ 我的理解 我的理解是本身service-serviceImpl结构,新增一个代理对象proxy,代理对象去直接访问serviceImpl,在proxy进行事务的增强操作,所以代理对象实现了接口。如何实现…...
Java八股文面试全套真题【含答案】-Vue篇
以下是一些关于Vue的经典面试题以及它们的答案: 什么是Vue.js?它有什么特点? 答案:Vue.js是一个用于构建用户界面的渐进式框架。它的特点包括双向数据绑定、组件化、虚拟DOM等。什么是Vue.js?它有什么特点?…...
介绍比特币上的 sCrypt 开发平台
最强大的基础设施和工具套件,可轻松构建和扩展您的 dApp 杀手级应用在哪里? 尽管比特币在小额支付、国际汇款和供应链管理等广泛用例中具有颠覆性潜力,但在推出 14 年后,我们还没有看到一款非常受欢迎并被主流采用的杀手级应用。 …...
什么是路由抖动?该如何控制
路由器在实现不间断的网络通信和连接方面发挥着重要作用,具有所需功能的持续可用的路由器可确保其相关子网的良好性能,由于网络严重依赖路由器的性能,因此确保您的路由器不会遇到任何问题非常重要。路由器遇到的一个严重的网络问题是路由抖动…...
2023SICTF-web-白猫-RCE
001 分析题目 题目名称: RCE 题目简介: 请bypass我! 题目环境: http://210.44.151.51:10088/ 函数理解: #PHP str_replace() 函数 <!DOCTYPE html> <html> <body><?php echo str_replace("…...
1.用数组输出0-9
文章目录 前言一、题目描述 二、题目分析 三、解题 程序运行代码 四、举一反三一、题目描述 二、题目分析 三、解题 程序运行代码 总结 前言 本系列为数组编程题,点滴成长,一起逆袭。 一、题目描述 用数组输出0-9 二、题目分析 数组下标从0开始 用数组…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
