零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(二)

零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(二) 参考教程https://www.bilibili.com/video/BV1L7411c7jw/?spm_id_from333.1387.favlist.content.click四、ESP8266作为网络服务器1、建立基本网络服务器1网络服务器有很多种类型通常承担网络服务器工作的设备都是运算能力比较强大的电脑。ESP866-NodeMCU虽然只能实现一些基本的网络服务功能不过这些基本的网络服务功能已经足够开发物联网项目了。2如果ESP866-NodeMCU作为服务器与电脑主机、手机都接入同一个Wi-Fi网络中那么电脑或者手机想要访问ESP866-NodeMCU的网站首页大致流程如下所示。3ESP8266WebServer类是网络服务器的抽象创建对象时需将应用层服务对应的运输层端口号传入构造函数中针对HTTP协议其使用的运输层熟知端口号为80。ESP8266WebServer类的成员函数有如下几个包括但不限于①begin启动ESP8266的网络服务功能该函数无参数。②on配置网络服务器如何处理用户端发来的不同的HTTP请求。其有三个参数第一个参数为用户端可能请求访问的网站目录以字符串的形式表示比如根目录“/”第二个参数为请求行中的方法可省略省略则不判断第三个参数为一个函数句柄当用户端用指定方法请求访问第一个参数指定的目录时服务器执行函数句柄指向的子函数子函数中一般有响应HTTP请求并发出响应报文的语句③onNotFound配置网络服务器如何处理用户端发来的无法满足的HTTP请求。其只有一个参数为一个函数句柄当用户端请求访问的目录不存在时服务器执行函数句柄指向的子函数子函数中一般有响应HTTP请求并发出“错误提示”响应报文的语句④send发送HTTP响应报文。其有三个参数第一个参数为状态码比如404表示找不到页面第二个参数为首部行的首部字段名比如“text/plain”表示纯文本“text/html”表示网页代码第三个参数为首部字段名对应的值比如纯文本对应的应为一段文本用户收到后将其解读为纯文本信息有时候没有需要特别添加的首部行则后两个参数可省略⑤handleClient处理客户端的请求这不是配置函数而是功能函数需要反复调用该函数无参数。4使用ESP8266实现最基本的网页服务功能其程序流程如下图所示。5将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板开启电脑热点“Zevalin_Computer”ESP8266会建立起一个小型服务器接下来打开浏览器在地址栏中输入NodeMCU的IP地址并按下回车可以看到“Hello from ESP8266”的文本信息。#include ESP8266WiFi.h //ESP8266WiFi库 #include ESP8266WiFiMulti.h //ESP8266WiFiMulti库 #include ESP8266WebServer.h //ESP8266WebServer库 ESP8266WiFiMulti wifiMulti; //建立ESP8266WiFiMulti对象,对象名称是wifiMulti ESP8266WebServer esp8266_server(80); //建立ESP8266WebServer对象对象名称为esp8266_server void handleRoot() { //处理网站根目录“/”的访问请求 esp8266_server.send(200, text/plain, Hello from ESP8266); } void handleNotFound(){ //处理404情况 esp8266_server.send(404, text/plain, 404: Not found); } void setup(void){ Serial.begin(9600); //启动串口通讯 //配置Wi-Fi网络的所有可能选项 wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); int i 0; while (wifiMulti.run() ! WL_CONNECTED) { //连接信号最强的Wi-Fi网络 delay(1000); Serial.print(i); Serial.print( ); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); //--------启动网络服务功能程序部分开始-------- esp8266_server.begin(); esp8266_server.on(/, handleRoot); esp8266_server.onNotFound(handleNotFound); //--------启动网络服务功能程序部分结束-------- Serial.println(HTTP esp8266_server started); //告知用户ESP8266网络服务功能已经启动 } void loop(void){ esp8266_server.handleClient(); //处理http服务器访问 }2、通过网络服务实现开发板基本控制1进一步介绍ESP8266WebServer类的成员函数①on函数除了能够配置收到用户端请求GET方法后给出相应的回应还能配置收到用户端请求POST请求后做出相应的行为比如“点灯”。②sendHeader函数用于向HTTP响应报文中的响应头部添加一个首部行它与send函数的区别是调用sendHeader添加首部行后不会将响应报文立即发送而调用send函数则会立即将响应报文立即发送且send函数会自动构建状态行、自动附加必要的头部。2使用ESP8266实现通过网络服务实现开发板基本的点灯控制其程序流程如下图所示。3将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板开启电脑热点“Zevalin_Computer”ESP8266会建立起一个小型服务器接下来打开浏览器在地址栏中输入NodeMCU的IP地址并按下回车可以看到一个标识文本为“Toggle LED”的按键按下它后浏览器向开发板发送POST请求开发板就会切换LED的状态同时浏览器的页面将跳转回根目录。#include ESP8266WiFi.h //ESP8266WiFi库 #include ESP8266WiFiMulti.h //ESP8266WiFiMulti库 #include ESP8266WebServer.h //ESP8266WebServer库 ESP8266WiFiMulti wifiMulti; //建立ESP8266WiFiMulti对象,对象名称是wifiMulti ESP8266WebServer esp8266_server(80); //建立ESP8266WebServer对象对象名称为esp8266_server void handleRoot() { //处理根目录请求网站主页给出一个“Toggle LED”按键按下它将用POST方法发送“/LED”的目录请求 esp8266_server.send(200, text/html, form action\/LED\ method\POST\input type\submit\ value\Toggle LED\/form); } void handleLED() { //处理LED控制请求 digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN)); //改变LED的点亮或者熄灭状态 esp8266_server.sendHeader(Location,/); //跳转回页面根目录 esp8266_server.send(303); //发送Http相应代码303跳转 } void handleNotFound(){ //处理404情况 esp8266_server.send(404, text/plain, 404: Not found); } void setup(void){ Serial.begin(9600); //启动串口通讯 pinMode(LED_BUILTIN, OUTPUT); //设置内置LED引脚为输出模式以便控制LED wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); int i 0; while (wifiMulti.run() ! WL_CONNECTED) { //连接信号最强的Wi-Fi网络 delay(1000); Serial.print(i); Serial.print( ); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); esp8266_server.begin(); //启动网站服务 esp8266_server.on(/, HTTP_GET, handleRoot); //设置服务器根目录即/的函数handleRoot esp8266_server.on(/LED, HTTP_POST, handleLED); //设置处理LED控制请求的函数handleLED esp8266_server.onNotFound(handleNotFound); //设置处理404情况的函数handleNotFound Serial.println(HTTP esp8266_server started); //告知用户ESP8266网络服务功能已经启动 } void loop(void){ esp8266_server.handleClient(); //处理http服务器访问 }3、通过网络服务将开发板引脚状态显示在网页中1为了便于学习本节将使用D3引脚作为演示案例因为它已经与开发板上的FLASH按键开关连接好了当没有按下该按键时D3引脚将会保持高电平状态当按下该按键时D3引脚会保持低电平状态。2使用ESP8266实现通过网络服务将开发板引脚状态显示在网页中其程序流程如下图所示。3将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板开启电脑热点“Zevalin_Computer”ESP8266会建立起一个小型服务器接下来打开浏览器在地址栏中输入NodeMCU的IP地址并按下回车可以看到网页中打印出D3引脚的电平信息按下FLASH开关不松开然后刷新网页可以看到网页中打印出D3引脚的电平信息发生变化。#include ESP8266WiFi.h //ESP8266WiFi库 #include ESP8266WiFiMulti.h //ESP8266WiFiMulti库 #include ESP8266WebServer.h //ESP8266WebServer库 #define buttonPin D3 //按钮引脚D3宏定义 ESP8266WiFiMulti wifiMulti; //建立ESP8266WiFiMulti对象,对象名称是wifiMulti ESP8266WebServer esp8266_server(80); //建立ESP8266WebServer对象对象名称为esp8266_server bool pinState; //存储引脚状态的变量 void handleRoot(){ String displayPinState; //定义存储按键状态的字符串变量 if(pinState HIGH){ //当按键引脚D3为高电平 displayPinState Button State: HIGH; //字符串赋值高电平信息 } else{ //当按键引脚D3为低电平 displayPinState Button State: LOW; //字符串赋值低电平信息 } esp8266_server.send(200, text/plain, displayPinState); //向浏览器发送按键状态信息 } void handleNotFound(){ //处理404情况 esp8266_server.send(404, text/plain, 404: Not found); } void setup(void){ Serial.begin(9600); //启动串口通讯 pinMode(buttonPin, INPUT_PULLUP); //将按键引脚设置为输入上拉模式 wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); int i 0; while (wifiMulti.run() ! WL_CONNECTED) { //连接信号最强的Wi-Fi网络 delay(1000); Serial.print(i); Serial.print( ); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); esp8266_server.begin(); //启动网站服务 esp8266_server.on(/, handleRoot); //设置服务器根目录的函数handleRoot esp8266_server.onNotFound(handleNotFound); //设置处理404情况的函数handleNotFound Serial.println(HTTP esp8266_server started); //告知用户ESP8266网络服务功能已经启动 } void loop(void){ esp8266_server.handleClient(); //不断处理http服务器访问 pinState digitalRead(buttonPin); //不断获取引脚状态 }4以上程序虽然能让客户端获取引脚状态但如果引脚状态更新而客户端又没有发送新的HTTP请求刷新网页相当于重新发出一次HTTP请求那么客户端显示的引脚状态是错误的。为了解决这个问题可以修改handleRoot函数使它向客户端发送的不再是简单的D3引脚电平状态字符串而是一串稍复杂的html代码其对应的网页除了打印D3引脚电平状态信息以外还会每隔5s自动刷新一次即发送一次新的HTTP请求这样服务器就能每隔5s将最新的D3引脚电平状态与客户端同步一次。void handleRoot() { //处理网站目录“/”的访问请求 esp8266_server.send(200, text/html, sendHTML(pinState)); } String sendHTML(bool buttonState){ String htmlCode !DOCTYPE html html\n; htmlCode headmeta http-equivrefresh content5/\n; //该页面每隔5s自动刷新一次也就是说每隔5s发出一次访问根目录请求 htmlCode titleESP8266 Butoon State/title\n; htmlCode stylehtml { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n; htmlCode body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n; htmlCode /style\n; htmlCode /head\n; htmlCode body\n; htmlCode h1ESP8266 BUTTON STATE/h1\n; if(buttonState) //根据D3引脚状态制定相应的html代码客户端接收后将其对应的网页信息打印在浏览器中 {htmlCode pButton Status: HIGH/p\n;} else {htmlCode pButton Status: LOW/p\n;} htmlCode /body\n; htmlCode /html\n; return htmlCode; }五、ESP8266闪存文件系统及应用1、ESP8266闪存文件系统介绍1通常来说ESP8266闪存文件系统Serial Peripheral Interface Flash File System有4MB的空间1MB空间用于存储应用程序3MB空间用于存储文件其中有一部分是系统文件不可修改。2SPIFFS是FS库提供的一个类或者说实例是对闪存文件系统的抽象。SPIFFS提供的几个成员函数如下①format函数用于清除闪存中专门用于存放文件的“SPIFFS文件系统分区”里的数据不会影响主程序。②begin函数用于启动闪存文件系统并返回启动结果True表示成功False表示失败失败并不意味着系统损坏可能是配置有问题导致的。③open函数用于以指定方式打开指定文件其第一个参数为文件路径或者说被操作文件的位置及名称第二个参数为打开方式字符串“w”表示写访问字符串“r”表示读访问字符串“a”表示追加信息。④exists函数用于判断闪存中是否有指定文件函数参数为文件路径或者说指定文件的位置及名称。⑤openDir函数用于打开指定路径的“目录”并返回一个Dir对象函数参数为被读取的文件夹路径。⑥remove函数用于移除指定文件函数参数为文件路径或者说指定文件的位置及名称如移除成功则返回True否则返回False如需要移除的文件本就不存在。⑦info函数用于获取闪存文件系统信息以FSInfo对象的类型返回。3File也是FS库提供的一个类是对文件的抽象使用open函数打开一个文件时open函数的返回值类型就是File。File类提供的成员函数如下①println函数向File对象指向的文件中写入字符串信息函数参数为字符串。用“w”方式打开文件时每次写入前都会先将文件原有内容清除而用“a”方式打开文件时每次写入都是直接在文件原有内容后面追加新内容②read函数从File对象指向的文件中读取一个字符的信息并返回然后文件指针右移一字节指向下一个字符。③close函数关闭File对象指向的文件防止其它代码段对文件进行误操作。④size函数获取File对象指向的文件大小并返回单位为字节。4Dir也是FS库提供的一个类是对目录的抽象有一个文件指针成员指向目录中的其中一个文件使用openDir函数打开一个文件夹时openDir函数的返回值类型就是Dir。Dir类提供的成员函数如下①next函数用于检查目录中是否还有“下一个文件”如有则返回True文件指针成员指向“下一个文件”如无则返回False。②fileName函数用于获取Dir对象的文件指针指向的文件的名称。5FSInfo也是FS库提供的一个类其成员属性是闪存文件系统的信息比如可用空间总和、已用空间等使用info函数获取闪存文件系统信息时info函数的返回值类型就是FSInfo。2、ESP8266闪存文件系统基本操作示例1在菜单栏中选择“工具”→“Flash Size”弹出的几个选项用于指示用户需要使用的闪存文件系统空间大小比如程序员需要使用1MB的闪存文件系统空间则选择“4MB(FS:1MB OTA:~1019KB)”即可。2将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可通过程序向闪存文件系统写入指定信息。#include FS.h String file_name /taichi-maker/notes.txt; //被读取的文件位置和名称 void setup() { Serial.begin(9600); Serial.println(); Serial.println(SPIFFS format start); SPIFFS.format(); //格式化闪存文件系统 Serial.println(SPIFFS format finish); if(SPIFFS.begin()){ //启动闪存文件系统 Serial.println(SPIFFS Started.); } else { Serial.println(SPIFFS Failed to Start.); } File dataFile SPIFFS.open(file_name, w); //建立File对象用于向SPIFFS中的file对象即/notes.txt写入信息 dataFile.println(Hello IOT World.); //向dataFile写入字符串信息 dataFile.close(); //完成文件写入后关闭文件 Serial.println(Finished Writing data to SPIFFS); } void loop() { }3在上一程序运行后将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可通过程序从闪存文件系统读取先前写入的信息。#include FS.h String file_name /taichi-maker/notes.txt; //被读取的文件位置和名称 void setup() { Serial.begin(9600); Serial.println(); if(SPIFFS.begin()){ //启动闪存文件系统 Serial.println(SPIFFS Started.); } else { Serial.println(SPIFFS Failed to Start.); } //确认闪存中是否有file_name文件 if (SPIFFS.exists(file_name)){ Serial.print(file_name); Serial.println( FOUND.); } else { Serial.print(file_name); Serial.print( NOT FOUND.); } //建立File对象用于从SPIFFS中读取文件 File dataFile SPIFFS.open(file_name, r); //读取文件内容并且通过串口监视器输出文件信息 for(int i0; idataFile.size(); i){ Serial.print((char)dataFile.read()); //从文件中读取1个字符并以char类型输出 } //完成文件读取后关闭文件 dataFile.close(); } void loop() { }4在上一程序运行后将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可通过程序向闪存文件系统中的文件添加信息。#include FS.h String file_name /taichi-maker/notes.txt; //被读取的文件位置和名称 void setup(){ Serial.begin(9600); Serial.println(); if(SPIFFS.begin()){ //启动闪存文件系统 Serial.println(SPIFFS Started.); } else{ Serial.println(SPIFFS Failed to Start.); } //确认闪存中是否有file_name文件 if (SPIFFS.exists(file_name)){ Serial.print(file_name); Serial.println( FOUND.); File dataFile SPIFFS.open(file_name, a); //建立File对象用于向SPIFFS中的file对象即/notes.txt写入信息 dataFile.println(This is Appended Info.); //向dataFile添加字符串信息 dataFile.close(); //完成文件操作后关闭文件 Serial.println(Finished Appending data to SPIFFS); } else{ Serial.print(file_name); Serial.print( NOT FOUND.); } } void loop(){ }5在上一程序运行后将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可通过程序读取闪存文件系统指定目录中的内容。#include FS.h String file_name /taichi-maker/myFile.txt; //被读取的文件位置和名称 String folder_name /taichi-maker; //被读取的文件夹 void setup(){ Serial.begin(9600); Serial.println(); if(SPIFFS.begin()){ //启动闪存文件系统 Serial.println(SPIFFS Started.); } else{ Serial.println(SPIFFS Failed to Start.); } File dataFile SPIFFS.open(file_name, w); //建立File对象用于向SPIFFS中的file对象即myFile.txt写入信息 dataFile.println(Hello Taichi-Maker.); //向dataFile写入字符串信息 dataFile.close(); //完成文件写入后关闭文件 Serial.println(F(Finished Writing data to SPIFFS)); //显示目录中文件内容以及文件大小 Dir dir SPIFFS.openDir(folder_name); //建立“目录”对象 while (dir.next()){ //dir.next()用于检查目录中是否还有“下一个文件” Serial.println(dir.fileName()); //输出文件名 } } void loop(){ }6在上一程序运行后将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可通过程序从闪存文件系统中删除指定文件。#include FS.h String file_name /taichi-maker/notes.txt; //被读取的文件位置和名称 void setup(){ Serial.begin(9600); Serial.println(); if(SPIFFS.begin()){ //启动闪存文件系统 Serial.println(SPIFFS Started.); } else{ Serial.println(SPIFFS Failed to Start.); } if (SPIFFS.remove(file_name)){ //从闪存中删除file_name文件 Serial.print(file_name); Serial.println( remove sucess); } else{ Serial.print(file_name); Serial.println( remove fail); } } void loop(){ }7在上一程序运行后将以下示例程序粘贴到代码区中然后将其编译并上传NodeMCU开发板这样即可通过程序获取闪存文件系统的信息如可用空间总和等。#include FS.h FSInfo fs_info; void setup(){ Serial.begin(9600); SPIFFS.begin(); //启动SPIFFS Serial.println(); Serial.println(SPIFFS Started.); //闪存文件系统信息 SPIFFS.info(fs_info); //可用空间总和单位字节 Serial.print(totalBytes: ); Serial.print(fs_info.totalBytes); Serial.println( Bytes); //已用空间单位字节 Serial.print(usedBytes: ); Serial.print(fs_info.usedBytes); Serial.println( Bytes); //最大文件名字符限制含路径和\0 Serial.print(maxPathLength: ); Serial.println(fs_info.maxPathLength); //最多允许打开文件数量 Serial.print(maxOpenFiles: ); Serial.println(fs_info.maxOpenFiles); //存储块大小 Serial.print(blockSize: ); Serial.println(fs_info.blockSize); //存储页大小 Serial.print(pageSize: ); Serial.println(fs_info.pageSize); } void loop(){ }3、通过Arduino IDE向闪存文件系统上传文件1准备工作之插件安装①进入Arduino-ESP8266官方GitHub页面下载Arduino-ESP8266闪存文件插件程序。Arduino-ESP8266官方GitHub页面的链接为https://github.com/esp8266/arduino-esp8266fs-plugin/releases。②在菜单栏中选择“文件”→“首选项”确定项目文件夹的路径。③打开Arduino IDE项目文件夹并在该路径下建立tools文件夹。④解压缩ESP8266FS插件压缩包并将解压缩后的文件内容粘贴到项目文件夹中。⑤重启Arduino IDE在菜单栏的“工具”子菜单中如有“ESP8266 Sketch Data Upload”选项说明插件安装成功需注意ESP8266FS插件不支持版本2.0以上的IDE版本2.x的IDE推荐使用LittleFS插件。2根据需要上传到闪存系统的文件大小在菜单栏中选择“工具”→“Flash Size”在弹出的几个选项中选择需要使用的闪存文件系统空间大小3将需要上传的文件保存在程序路径下的data文件夹中。4在菜单栏的“工具”子菜单中点击“ESP8266 Sketch Data Upload”选项即可将data中的文件上传到闪存文件系统中。4、使用闪存文件系统建立功能丰富的网络服务器1示例1在网页中加载闪存文件系统中的图片文件、html文件、css文件和js文件。①程序流程示意图②下载至开发板的代码#include ESP8266WiFi.h #include ESP8266WiFiMulti.h #include ESP8266WebServer.h #include FS.h ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象 ESP8266WebServer esp8266_server(80); // 建立网络服务器对象该对象用于响应HTTP请求。监听端口80 void setup() { Serial.begin(9600); // 启动串口通讯 Serial.println(); wifiMulti.addAP(Zevalin_Computer, 00114514); wifiMulti.addAP(Zevalin_esp8266, 00114514); Serial.println(Connecting ...); int i 0; while (wifiMulti.run() ! WL_CONNECTED) { delay(1000); Serial.print(i); Serial.print( ); } Serial.println(\n); Serial.print(Connected to ); Serial.println(WiFi.SSID()); Serial.print(IP address:\t); Serial.println(WiFi.localIP()); if(SPIFFS.begin()){ // 启动闪存文件系统 Serial.println(SPIFFS Started.); } else { Serial.println(SPIFFS Failed to Start.); } esp8266_server.onNotFound(handleUserRequet); // 告知系统如何处理用户请求 esp8266_server.begin(); // 启动网站服务 Serial.println(HTTP server started); } void loop(void) { esp8266_server.handleClient(); // 处理用户请求 } // 处理用户浏览器的HTTP访问 void handleUserRequet() { // 获取用户请求网址信息 String webAddress esp8266_server.uri(); // 通过handleFileRead函数处理用户访问 bool fileReadOK handleFileRead(webAddress); // 如果在SPIFFS无法找到用户访问的资源则回复404 (Not Found) if (!fileReadOK){ esp8266_server.send(404, text/plain, 404 Not Found); } } bool handleFileRead(String path) { //处理浏览器HTTP访问 if (path.endsWith(/)) { // 如果访问地址以/为结尾 path /index.html; // 将访问地址修改为/index.html便于SPIFFS访问 } String contentType getContentType(path); // 获取文件类型 if (SPIFFS.exists(path)) { // 如果访问的文件可以在SPIFFS中找到 File file SPIFFS.open(path, r); // 尝试打开该文件 esp8266_server.streamFile(file, contentType);// 将该文件返回给浏览器 file.close(); // 关闭文件 return true; // 返回true } return false; // 如果文件未找到则返回false } // 获取文件类型 String getContentType(String filename){ if(filename.endsWith(.htm)) return text/html; else if(filename.endsWith(.html)) return text/html; else if(filename.endsWith(.css)) return text/css; else if(filename.endsWith(.js)) return application/javascript; else if(filename.endsWith(.png)) return image/png; else if(filename.endsWith(.gif)) return image/gif; else if(filename.endsWith(.jpg)) return image/jpeg; else if(filename.endsWith(.ico)) return image/x-icon; else if(filename.endsWith(.xml)) return text/xml; else if(filename.endsWith(.pdf)) return application/x-pdf; else if(filename.endsWith(.zip)) return application/x-zip; else if(filename.endsWith(.gz)) return application/x-gzip; return text/plain; }streamFile函数是ESP8266WebServer库中一个非常重要且高效的方法它的核心作用是直接将一个文件例如闪存中的文件以流式streaming的方式作为HTTP响应的正文发送给客户端比如浏览器它有两个参数第一个是已打开的File对象引用指向想要发送的文件第二个是一个字符串指定了文件的MIME类型告诉浏览器如何解析这个文件例如text/html 表示网页image/jpeg 表示JPEG图片③闪存系统中的文件文件的编写非本教程重点具体可在前端相关教程中了解​​​​​​​[1]taichi-maker.jpg文件在根目录下的img文件夹中​​​​​​​[2]clock.js文件在根目录中/** * 动态显示当前时间 */ function showDateTime(){ var sWeeknew Array(日,一,二,三,四,五,六); //声明数组存储一周七天 var myDatenew Date(); //获取当天日期 var sYearmyDate.getFullYear(); //获取年 var sMonthmyDate.getMonth()1; //获取月 var sDatemyDate.getDate(); //获取日 var sDaysWeek[myDate.getDay()]; //根据得到的数字星期,利用数组转化为星期 var hmyDate.getHours(); //获取小时 var mmyDate.getMinutes(); //获取分钟 var smyDate.getSeconds(); //获取秒 //输入日期和星期 document.getElementById(date).innerHTML(sYear年sMonth月sDate日星期sDaybr/); h formatTwoDigits(h); //格式化小时,如果不足两位在前面补0 m formatTwoDigits(m); //格式化分钟,如果不足两位在前面补0 s formatTwoDigits(s); //格式化秒钟后,如果不足两位在前面补0 //显示时间 document.getElementById(msg).innerHTML(h:m:sbr/); setTimeout(showDateTime(),1000);//每秒执行一次showDateTime函数 } window.onloadshowDateTime;//在整个页面加载完成后执行此函数 //如果输入数是一位数,则在十位上补0 function formatTwoDigits(s) { if (s10) return 0s; else return s; }[3]JavaScript.js文件在根目录中setTimeout(function() { let jsParagraph document.createElement(p); jsParagraph.textContent Hello from JavaScript.js!; document.body.appendChild(jsParagraph); }, 1000);[4]main.css文件在根目录中body { font-family: sans-serif; color: #444; } p.red { color: red; }[5]index.html文件在根目录中!DOCTYPE html html langzh-CN head meta charsetUTF-8 link relstylesheet typetext/css hrefmain.css title太极创客-零基础入门学用物联网教程/title script typetext/javascript srcclock.js/script /head body center a hrefhttp://www.taichi-maker.com target_blackimg src/img/taichi-maker.jpg alt太极创客/a h1ESP8266 SPIFFS web server示例/h1 p此页面用于演示如何通过ESP8266开发板的SPIFFS中读取文件并显示于浏览器中。/p p本教程可在太极创客网站免费获取。太极创客网址 a hrefhttp://www.taichi-maker.com target_blackwww.taichi-maker.com/a . p classred创建页面时可以使用css。这里的字体是红色原因是使用了css。/p !--显示时钟-- h3页面支持JavaScript以下时钟/日期使用JavaScript实现。/h3 h1 iddate/h1 span idmsg stylefont-size: 30px;background-color: greenyellow;/span /center /body /html