ndfweb.cn

Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:静态文件和模板引擎


2021-08-28 22:12:10 (4493)


对于WebServer来说静态文件也是非常重要的一块。通常一个网页有很多文件组成,比如一个主页通常由index.html、favicon.ico等多个文件组成,用户访问 /index.html 时,浏览器接收到 index.html 文件后还会再请求该文件中关联的其它文件,这些文件名称和类型等都是无法预料的,一条条添加对应的url就非常不方便了,这个时候就需要用到静态文件服务了。

静态文件中通常可以使用模板引擎方便的实现界面与数据的分离,减少开发过程中的工作量,特定情景下还是蛮好用的。

这篇文章将对上面两块相关内容进行介绍。


本文中各例程演示均在ESP32中进行。


静态文件服务


功能说明


使用静态文件服务首先需要启动相关的文件系统,除了可以使用Flash上的SPIFFS系统,还可以使用SD卡等。初始完成后就可以用 AsyncWebServer 对象的 serveStatic() 方法来设置静态文件服务了,比如下面这样:


// 用户访问/page.htm时,返回SPIFFS中/www/page.htm文件

server.serveStatic("/page.htm", SPIFFS, "/www/page.htm");

1

2

上面的方式指定了文件到文件,事实上大多数情况是不会这么用的,而是下面这样:


// 用户访问/目录下文件时返回SPIFFS中/www/路径下同名文件

// 比如用户访问/page.htm时,将会返回SPIFFS中/www/page.htm文件

// 比如用户访问/favicon.ico时,将会返回SPIFFS中/www/favicon.ico文件

// ……

// 特殊情况:用户访问/时,默认将会返回SPIFFS中/www/index.htm文件(如果存在)

server.serveStatic("/", SPIFFS, "/www/");

1

2

3

4

5

6

上面上面的使用方式是最常用的方式,上面的方式中有一种特殊情况,就是用户访问根目录时返回了index.htm文件,这个默认返回的文件也可以手动定义,使用下面方法:


// 用户访问/时,默认返回将变成SPIFFS中/www/default.html文件

server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("default.html");

1

2

客户端如果多次打开网页,每次都从服务器获取静态文件的话对性能影响还是蛮大的,这时候就可以使用Cache-Control和Last-Modified来优化性能。

Cache-Control可以设定一个时间,客户端在获取到某个文件后将文件进行缓存,这段时间内如果再需要这个文件的话将不再从服务器获取,而是直接使用缓存。下面是Cache-Control的使用示例:


// 设定缓存事件600秒,客户端获取过的文件将在客户端缓存600秒

// 600秒内需要已缓存的文件将直接使用缓存,不再从服务器获取

server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=600");


// 使用下面方式就可以随时更改Cache-Control

AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/").setCacheControl("max-age=600");

handler->setCacheControl("max-age=30");

1

2

3

4

5

6

7

Cache-Control除了上面功能外还有很多别的功能,不同功能下setCacheControl中填入的参数不同,比如填入 "no-store" 参数的话将禁用所有缓存。Cache-Control参数更多内容可以参考 Cache-Control 。


Last-Modified将设置一个时间参数,客户端如果缓存过文件,下次再需要该文件向服务器请求时将附带缓存文件的时间参数,服务器比较两个参数,如果服务器中的参数较新的话将发送新的文件,否则客户端将使用缓存文件。下面是Last-Modified的使用示例:


// 设定文件最后修改时间参数

AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/").setLastModified("Mon, 26 Apr 2010 13:22:17 GMT");

Mon, 26 Apr 2010 13:22:17 GMT


// 更新文件最后修改时间参数

handler->setLastModified("Mon, 20 Jun 2016 14:00:00 GMT");

1

2

3

4

5

6

静态文件服务可以设置身份认证,用户必须通过认证后才能访问其中的文件:


// setAuthentication()中分别填入用户名和密码

server.serveStatic("/", SPIFFS, "/www/").setAuthentication("user", "pass");

1

2

除了上面的功能外静态文件服务还可以应用过滤器和模板引擎。下面是应用过滤器的示例(模板引擎的示例将在模板引擎章节介绍):


server.serveStatic("/", SPIFFS, "/www/").setFilter(ON_STA_FILTER); // ESP32处于STA模式时起效

server.serveStatic("/", SPIFFS, "/ap/").setFilter(ON_AP_FILTER); // ESP32处于AP模式时起效

1

2

从上面的介绍可以看到静态文件服务可选的参数非常多,如果需要设置多个参数的话可以使用下面两种方式:


// 方式一

server.serveStatic("/", SPIFFS, "/www/").setDefaultFile("default.html").setCacheControl("max-age=600");


// 方式二

AsyncStaticWebHandler* handler = &server.serveStatic("/", SPIFFS, "/www/");

handler->setDefaultFile("default.html");

handler->setCacheControl("max-age=600");

1

2

3

4

5

6

7

使用演示


这里以使用SPIFFS作为文件系统进行静态文件服务功能演示,首先准备几个文件。将下面文本保存为名为index.html的文件:


<!DOCTYPE html>

<head>

    <meta charset="UTF-8">

    <title>ServeStatic Test</title>

    <link rel="stylesheet" type="text/css" href="mystyle.css">

</head>

<body>

    <p>这是静态文件服务测试</p>

    <p>本页面的背景颜色是由mystyle.css文件提供的</p>

    <p>本页面引用了mystyle.css文件,浏览器在解析时会自动向服务器请求该文件</p>

</body>

</html>

1

2

3

4

5

6

7

8

9

10

11

12

将下面文本保存为名为mystyle.css的文件:


body {

    background-color: gray;

}

1

2

3

在Arduino中使用下面代码:


#include <WiFi.h>

#include <SPIFFS.h>

#include <ESPAsyncWebServer.h> //引入相应库


const char *ssid = "********";

const char *password = "********";


AsyncWebServer server(80); //声明WebServer对象


void setup()

{

  Serial.begin(115200);

  Serial.println();


  WiFi.mode(WIFI_STA);

  WiFi.setSleep(false);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)

  {

    delay(500);

    Serial.print(".");

  }

  Serial.println("Connected");

  Serial.print("IP Address:");

  Serial.println(WiFi.localIP());


  SPIFFS.begin(true); //挂载SPIFFS,如果挂载失败则格式化生成SPIFFS,格式化时间较长

  //当然上面begin中不填true格式化也行,下面演示中用工具上传文件时会自动生成SPIFFS


  server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");


  server.begin(); //启动服务器


  Serial.println("Web server started");

}


void loop(){}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37


上面使用了名为 ESP32 Sketch Data Upload 的工具来将 项目文件夹下data文件夹中 的网页相关文件上传到ESP32的SPIFFS中。一切就绪后在浏览器中访问就可以看到网页被正确的加载出来了,单独访问两个文件也没问题。


上传文件用到的工具项目地址如下:

https://github.com/me-no-dev/arduino-esp32fs-plugin

从项目地址下载Release版本压缩包,将其解压到Arduino安装文件夹tools文件夹下,最终文件路径为: .../Arduino/tools/ESP32FS/tool/esp32fs.jar 。重启Arduino IDE后就可以在菜单中看到选项。


ESP8266上传文件到SPIFFS的工具项目地址如下:

https://github.com/esp8266/arduino-esp8266fs-plugin


SPIFFSEditor


ESPAsyncWebServer库中有一个SPIFFSEditor功能,可以通过网页管理和编辑文件系统中的文件,这里做个简单的使用演示:


#include <WiFi.h>

#include <SPIFFS.h>

#include <ESPAsyncWebServer.h> //引入相应库

#include <SPIFFSEditor.h> //引入相应库


const char *ssid = "********";

const char *password = "********";


AsyncWebServer server(80); //声明WebServer对象


const char* http_username = "admin";

const char* http_password = "123456";


void setup()

{

  Serial.begin(115200);

  Serial.println();


  WiFi.mode(WIFI_STA);

  WiFi.setSleep(false);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)

  {

    delay(500);

    Serial.print(".");

  }

  Serial.println("Connected");

  Serial.print("IP Address:");

  Serial.println(WiFi.localIP());


  SPIFFS.begin(true);


  server.addHandler(new SPIFFSEditor(SPIFFS, http_username,http_password));


  server.begin(); //启动服务器


  Serial.println("Web server started");

}


void loop(){}



上面就是SPIFFSEditor的演示了,需要注意的是SPIFFSEditor的网页中用到了外部的文件,需要能连上互联网才能正确加载。


模板引擎


ESPAsyncWebServer中的模板引擎目前只支持一个功能,实际值替换占位符。该模板引擎使用 % 来标识占位符,先看下面演示:


#include <WiFi.h>

#include <ESPAsyncWebServer.h> //引入相应库


const char *ssid = "********";

const char *password = "********";


AsyncWebServer server(80); //声明WebServer对象


int count = 0;


String processor(const String& var)

{

  if(var == "VAR1")

  {

    count++;

    return String(count);

  }

  else if(var == "VAR2")

  {

    return "lalala~~~";

  }

  else if(var == "VAR3")

  {

    return F("ABCDEFG"); // F() 是Arduino的PROGMEM机制,里面的字符串将存放在Flash中,减少对内存的占用

  }

  return String();

}


void handleRoot(AsyncWebServerRequest *request) //回调函数

{

   // 向客户端发送响应和内容

   // 注意文本中用 % % 包围的字符串,

  request->send_P(200, "text/plain", "count = %VAR1%, VAR2 = %VAR2%, VAR3 = %VAR3%", processor);

}


void setup()

{

  Serial.begin(115200);

  Serial.println();


  WiFi.mode(WIFI_STA);

  WiFi.setSleep(false);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)

  {

    delay(500);

    Serial.print(".");

  }

  Serial.println("Connected");

  Serial.print("IP Address:");

  Serial.println(WiFi.localIP());


  server.on("/", HTTP_GET, handleRoot); //注册链接"/"与对应回调函数


  server.begin(); //启动服务器


  Serial.println("Web server started");

}


void loop(){}



ESPAsyncWebServer的模板引擎因为功能单一,从上面的演示中就可以完全理解了,模板引擎经常用在静态的文件中。除了上面演示用的方式还可以用下面的方式来使用:


const char index_html[] PROGMEM = "..."; // large char array, tested with 14k

AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html);

request->send(response);

1

2

3

或者直接在静态文件服务上使用也可以:


String processor(const String& var)

{

  if(var == "HELLO_FROM_TEMPLATE")

    return F("Hello world!");

  return String();

}


// ...


server.serveStatic("/", SPIFFS, "/www/").setTemplateProcessor(processor);


了解更多请访问:http://www.ndfweb.cn/news-904.html
  NDF俱乐部
  国际域名注册
  建站咨询
合作伙伴:万网 | 新网 | 新网互联 NDF网站建设淘宝店 | 实用工具 | 外貿網站建設 | 联系我们
鲁公网安备 37110202000336号 鲁ICP备2021027697号-1 Sitemap - RSSRSS订阅