上一篇貼文的網站伺服器程式,需要手動處理檔案路徑和內容類型,本單元將加入自動判斷資源內容類型,並且自動傳送指定路徑的資源的程式。
自動設定資源的內容類型
底下的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()方法,檢查字串是否以指定的內容結尾。例如:
因此,假若檔名路徑的結尾是“.htm”或“.html”,此函式將傳回“text/html”內容類型。
自動處理檔案路徑
底下「處理檔案讀取」的handleFileRead()函式,也是修改自FSBrowser原始碼。此函式接收一個path(路徑)參數,如果參數值為“/”,程式將把路徑改成“/index.htm”,然後透過SPIFFS物件的exists()方法判斷此檔案是否存在於快閃記憶體,若有,則執行server.streamFile()把檔案傳給用戶端。
上面的程式同樣執行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”,即可看見如下的圖文網頁:
未完…待續。
老师您好,对于“請把處理根路徑的事件程式,改寫在處理「不存在的」路徑的函式裡面”这句话我不是很理解,可以请你解释一下,为什么浏览器输入IP地址后,会触发server.onNotFound吗?
对,请比较「在ESP8266的SPIFFS檔案系統存放網頁檔案(一)」这篇文章的代码,包含处理根路径请求的事件:
server.on(“/”, rootRouter);
server.on(“/index.htm”, rootRouter);
这篇文章的代码并没有这两个陈述,因此所有路径请求都会触发server.onNotFound事件。
thanks,
jeffrey
老师,您好,我还想问一下下面这个代码(省略了一点内容)
File message_file=SFIFFS.open(“data.txt”);
medium_message+=char(message_file.read());
return medium_message;
最后返回的 medium_message的内容就是data.txt这个文件里的内容吗?是字符型的?
对,因为已经转成char型。
thanks,
jeffrey
老师,
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?
负责处理网页路径请求的是server.on(),如果没有设置的话,就会触发server.onNotFound。
thanks,
jeffrey