WiFi-ESP8266入門http(2-1)文件系統-復雜結構的網頁


https://blog.csdn.net/solar_Lan/article/details/74231360

用到的網頁文件:鏈接:https://pan.baidu.com/s/1vk6xmsYZuJe8CMFzJNKdJw 密碼:oiz2

注:對於ESP8266開源技術感興趣的可以加群,我們一起探索交流學習,群號:579932824。群名:ESP8266開源技術交流群。

在第一篇教程中,由ESP8266返回的網頁都是通過直接發送String來完成響應,這個方法是挺快的,但是在復雜結構的網頁下就顯得格外麻煩,調整的時候需要一個個找,而且還是在html結構打亂的情況下找,把css和js寫入到同一個頁面內無疑也是增加了調試的成本,

所以官方引入了一個SPIFFS的文件系統(SPIFFS的github地址:https://github.com/pellepl/spiffs),

這個文件系統是通過共用板載的Flash芯片來完成

(官方說明文檔:https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md),

之前在配置環境的時候相比應該還記得有個選擇Flash Size的選項吧,這個就是分配程序和SPIFFS空間的選項。一般市面上的12E型都已經搭載了4M的Flash,所以大家在選擇的時候就選擇使用4M的,剩下是1M還是3M的SPIFFS就看實際需要,一般推薦使用1M,因為燒寫SPIFFS的時候不像燒寫程序那樣只是根據程序大小燒寫部分區塊,而是整個區塊完整燒寫的,3M燒寫一次的時間差不多有4-5分鍾,燒寫1M的則會很快。

這次教程的代碼:

#include <ESP8266WiFi.h>  

#include <ESP8266WebServer.h>  

#include <FS.h>  

ESP8266WebServer server ( 80 );  

String ssid = "...."; // 需要連接的wifi熱點名稱  

String password = "........"; // 需要連接的wifi熱點密碼  

/** 

 * 根據文件后綴獲取html協議的返回內容類型 

 */  

String getContentType(String filename){  

  if(server.hasArg("download")) return "application/octet-stream";  

  else 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";  

}  

/* NotFound處理 

 * 用於處理沒有注冊的請求地址 

 * 一般是處理一些頁面請求 

 */  

void handleNotFound() {  

  String path = server.uri();  

  Serial.print("load url:");  

  Serial.println(path);  

  String contentType = getContentType(path);  

  String pathWithGz = path + ".gz";  

  if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){  

    if(SPIFFS.exists(pathWithGz))  

      path += ".gz";  

    File file = SPIFFS.open(path, "r");  

    size_t sent = server.streamFile(file, contentType);  

    file.close();  

    return;  

  }  

  String message = "File Not Found\n\n";  

  message += "URI: ";  

  message += server.uri();  

  message += "\nMethod: ";  

  message += ( server.method() == HTTP_GET ) ? "GET" : "POST";  

  message += "\nArguments: ";  

  message += server.args();  

  message += "\n";  

  for ( uint8_t i = 0; i < server.args(); i++ ) {  

    message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";  

  }  

  server.send ( 404, "text/plain", message );  

}  

void handleMain() {  

  /* 返回信息給瀏覽器(狀態碼,Content-type, 內容) 

   * 這里是訪問當前設備ip直接返回一個String 

   */  

  Serial.print("handleMain");  

  File file = SPIFFS.open("/index.html", "r");  

  size_t sent = server.streamFile(file, "text/html");  

  file.close();  

  return;  

}  

/* 引腳更改處理 

 * 訪問地址為htp://192.162.xxx.xxx/pin?a=XXX的時候根據a的值來進行對應的處理 

 */  

void handlePin() {  

  if(server.hasArg("a")) { // 請求中是否包含有a的參數  

    String action = server.arg("a"); // 獲得a參數的值  

    if(action == "on") { // a=on  

      digitalWrite(2, LOW); // 點亮8266上的藍色led,led是低電平驅動,需要拉低才能亮  

      server.send ( 200, "text/html", "Pin 2 has turn on"); return; // 返回數據  

    } else if(action == "off") { // a=off  

      digitalWrite(2, HIGH); // 熄滅板載led  

      server.send ( 200, "text/html", "Pin 2 has turn off"); return;  

    }  

    server.send ( 200, "text/html", "unknown action"); return;  

  }  

  server.send ( 200, "text/html", "action no found");  

}  

void setup() {   

  // 日常初始化網絡  

  pinMode(2, OUTPUT);  

  Serial.begin ( 115200 );  

  SPIFFS.begin();  

  int connectCount = 0;  

  WiFi.begin ( ssid.c_str(), password.c_str() );  

  while ( WiFi.status() != WL_CONNECTED ) {  

    delay ( 1000 );  

    Serial.print ( "." );  

    if(connectCount > 30) {  

      Serial.println( "Connect fail!" );  

      break;  

    }  

    connectCount += 1;  

  }  

  if(WiFi.status() == WL_CONNECTED) {  

    Serial.println ( "" );  

    Serial.print ( "Connected to " );  

    Serial.println ( ssid );  

    Serial.print ( "IP address: " );  

    Serial.println ( WiFi.localIP() );  

    connectCount = 0;  

  }  

  server.on ("/", handleMain); // 綁定‘/’地址到handleMain方法處理  

  server.on ("/pin", HTTP_GET, handlePin); // 綁定‘/pin’地址到handlePin方法處理  

  server.onNotFound ( handleNotFound ); // NotFound處理  

  server.begin();  

  Serial.println ( "HTTP server started" );  

}  

   

void loop() {  

  /* 循環處理,因為ESP8266的自帶的中斷已經被系統占用, 

   * 只能用過循環的方式來處理網絡請求 

   */  

  server.handleClient();  

}  

  

代碼修改自之前路由系統,畢竟web頁面配合路由的請求會很方便。

主要是增加了getContentType方法和修改了handleMain、handleNotFound。修改handleMain引導訪問根目錄到index.html文件上,修改handleNotFound加入文件檢查,有則直接返回,沒有則404。

需要用到的css和js文件(度盤連接),這里的文件是壓縮成gz格式,在瀏覽器中是支持這種格式的壓縮文件的,壓縮成gz的目的是減少數據量,節約傳輸的帶寬,8266雖然說是54M的制式,但是從Flash讀取出數據再傳輸到客戶端上的數據流量大約只有6-9kb/s,一個jquery min沒壓縮前大約94kb,最快的情況傳輸需要10秒鍾,而壓縮成gz格式之后只有32kb,傳輸也就只需要3秒鍾,中間的等待時間就少了很多。在handleNotFound里邊做了判斷,如果找到同名文件帶有gz格式的文件優先返回gz文件。

接下來就是將文件上傳到Flash上了,在這里需要下載一個Arduino IDE的插件(github地址:https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.3.0/ESP8266FS-0.3.0.zip,度盤:)。下載完成之后解壓到IDE的tools文件夾中,解壓之后完整的路徑應該是“Arduino IDE的文件夾/tools/ESP8266FS/tool/esp8266fs.jar”,然后重啟Arduino IDE,打開項目,在對應的項目文件夾下創建名稱為data的文件夾,這個data文件夾就是上傳數據用的文件夾,上傳之后這個目錄就是8266的根目錄,將需要上傳的文件復制到這個文件夾中,讓8266進入燒寫狀態並關閉IDE的串口管理器,最后選擇Tools(工具)->ESP8266 Sketch Data Upload選項,將文件上傳到給8266的板載Flash。進入燒寫狀態之后就慢慢等着文件上傳完成了,完成之后8266會重啟,但是保險起見,建議手動重啟一次。

之后待8266連接上wifi之后訪問它在串口管理器打印的IP,就可以看到上傳到8266上的頁面了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM