ndfweb.cn

Arduino for ESP8266&ESP32適用庫ESPAsyncWebServer:靜態文件和模板引擎


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



對於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网站建设淘宝店 | ICO图标在线生成 | 外贸网站建设 | 联系我们
©2007-2024 NDF Corporation 鲁ICP备08005967号 Sitemap - RSSRSS订阅