在ESP8266的SPIFFS檔案系統存放網頁檔案(二)

上一篇貼文的網站伺服器程式,需要手動處理檔案路徑和內容類型,本單元將加入自動判斷資源內容類型,並且自動傳送指定路徑的資源的程式。

自動設定資源的內容類型

底下的getContentType()自訂函式,可自動判別檔案的內容類型。此函式取自ESP8266WebServer程式庫裡的FSBrowser原始碼,它接收一個檔名(filename)參數,並傳回字串格式的內容類型資料:

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

此函式透過String物件的endsWith()方法,檢查字串是否以指定的內容結尾。例如:

String物件的endsWith()方法

因此,假若檔名路徑的結尾是“.htm”或“.html”,此函式將傳回“text/html”內容類型。

自動處理檔案路徑

底下「處理檔案讀取」的handleFileRead()函式,也是修改自FSBrowser原始碼。此函式接收一個path(路徑)參數,如果參數值為“/”,程式將把路徑改成“/index.htm”,然後透過SPIFFS物件的exists()方法判斷此檔案是否存在於快閃記憶體,若有,則執行server.streamFile()把檔案傳給用戶端。

自動處理檔案路徑的handleFileRead()函式

上面的程式同樣執行String物件的endsWith()方法確認路徑:

執行String物件的endsWith()方法確認路徑

加入以上兩個新程式片段之後,請把處理根路徑的事件程式,改寫在處理「不存在的」路徑的函式裡面

處理「不存在的」路徑的事件程式

完整的程式碼如下:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <FS.h>

const char ssid[] = "你的WiFi網路SSID";
const char pass[] = "你的WiFi密碼";
const char* host = "jarvis";

ESP8266WebServer server(80);

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

bool handleFileRead(String path){
  Serial.println("handleFileRead: " + path); // 在序列埠顯示路徑

  if (path.endsWith("/")) {
    path += "index.htm";
  }

  String contentType = getContentType(path);
  
  if (SPIFFS.exists(path)){
    File file = SPIFFS.open(path, "r");
    server.streamFile(file, contentType);
    file.close();

    return true;
  }
  return false;
}

void setup( ){
  Serial.begin(115200);

  SPIFFS.begin();  // 啟用SPIFFS檔案系統

  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  IPAddress ip = WiFi.localIP();
  
  if (!MDNS.begin(host, ip)) {
    Serial.println("Error setting up MDNS responder!");
    while(1) { 
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  server.onNotFound([](){
    if (!handleFileRead(server.uri())) {
      server.send(404, "text/plain", "FileNotFound");
    }
  });

  server.begin();
  Serial.println("HTTP server started");

  MDNS.setInstanceName("Cubie's ESP8266");
  MDNS.addService("http", "tcp", 80);
}
 
void loop( ){
  server.handleClient();
}

重新編譯、上傳此程式碼,再連結到“jarvis.local”,即可看見如下的圖文網頁:

jarvis.local網頁

未完…待續。

延伸閱讀

Posts created 467

6 thoughts on “在ESP8266的SPIFFS檔案系統存放網頁檔案(二)

  1. 老师您好,对于“請把處理根路徑的事件程式,改寫在處理「不存在的」路徑的函式裡面”这句话我不是很理解,可以请你解释一下,为什么浏览器输入IP地址后,会触发server.onNotFound吗?

  2. 老师,您好,我还想问一下下面这个代码(省略了一点内容)
    File message_file=SFIFFS.open(“data.txt”);

    medium_message+=char(message_file.read());

    return medium_message;
    最后返回的 medium_message的内容就是data.txt这个文件里的内容吗?是字符型的?

  3. 老师,
    File file=SFIFFS.open(“data.txt”);
    message+=char(file.read());
    在这个基础上,如果我将message的内容通过server.send(200, “text/html”, “message”);发给浏览器后,浏览器的IP地址是会变成http/…/…/…/…/data.txt吗?
    如果我没有设置server.on(“/data.txt”, rootRouter);,是不是也会触发server.onNotFound?

    1. 负责处理网页路径请求的是server.on(),如果没有设置的话,就会触发server.onNotFound。

      thanks,
      jeffrey

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top