本單元的程式修改自《超圖解物聯網IoT實作入門》第13章「使用ESP-01模組開發Arduino物聯網」單元,程式架構不變,只是把原本引用自CDN網路的jQuery程式和CSS樣式,改成存入ESP8266控制板的SPIFFS記憶體區域。
由於ESP8266的快閃記憶體空間有限(以4MB為例,可分配給SPIFFS使用的大小為3MB),網頁的資源(如:HTML, JavaScript和CSS)存入ESP8266之前,最好先壓縮。網頁的GIF, JPEG和PNG影像檔本身已經過最佳化處理,所以不必再壓縮。
使用GZip壓縮網頁資源:節省檔案空間與網路頻寬
GZip是Linux/UNIX系統常見的壓縮格式(副檔名以.gz結尾),相當於Windows系統上的Zip壓縮格式。GZip和Zip的主要差別是,Zip可以壓縮資料夾和多個檔案,GZip只能壓縮單一檔案。因此,在Linux/Unix上,壓縮目錄或多個檔案之前,需要先透過tar工具程式把目錄或多個檔案封裝(打包)成單一的.tar檔,再使用gzip工具壓縮。
Windows系統的免費7-Zip工具有支援GZip格式壓縮和解壓縮。Mac OS X系統可直接雙按.gz檔將它解壓縮,或者在終端機視窗中,輸入”gunzip -d 壓縮檔路徑和檔名“命令,也能將它解壓縮,解壓縮之後,原本的.gz壓縮檔會被刪除。
為了節省網路頻寬,所有瀏覽器都支援.gz壓縮格式(以微軟的IE為例,從古早的4.0版就支援了)。不過,網頁設計師並不需要自行以gzip壓縮網頁相關檔案,因為網站伺服器軟體(如:Apache, Nginx, IIS,…等)都能自動壓縮內容。您正在閱讀的這篇文章,也是經過網站伺服器自動壓縮之後才傳送到您的瀏覽器。
當瀏覽器發出連結網站請求時,會透過HTTP檔頭的Accept-Encoding欄位,告訴網站伺服器它所接受的編碼類型:
網站伺服器收到上面的請求,得知用戶端支援gzip壓縮,就能先以gzip壓縮內容再回應用戶。
上傳jQuery和CSS樣式與影像檔到SPIFFS區域
ESP8266的網站伺服器程式無法即時壓縮內容,因此我們必須事先自行壓縮檔案,再上傳到ESP8266。底下是本單元的data資料夾內容(請按此連結下載本單元的原始檔):
修改書本範例網頁的HTML,把原本引用CDN的CSS和jQuery檔案路徑,改成直接引用本機檔案的路徑。以jQuery UI為例,原本的路徑是:
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
請改成(資源檔名不要用.gz結尾):
<script src="js/jquery-ui.min.js"></script>
開啟ESP01.ino檔案之後,執行主功能表的「工具→ESP8266 Sketch Data Upload」(ESP8266草稿碼資料上傳)指令,上傳網頁資源。
相較於上一篇貼文中「處理檔案讀取」的handleFileRead()函式,本單元的函式需要在請求的資源路徑後面加入“.gz”結尾:
可傳回.gz檔的handleFileRead()函式:
bool handleFileRead(String path){ Serial.println("handleFileRead: " + path); if(path.endsWith("/")) path += "index.htm"; String contentType = getContentType(path); String pathWithGz = path + ".gz"; // 路徑結尾加上".gz" // 確認請求路徑或者.gz結尾的資源存在 if( SPIFFS.exists(path) || SPIFFS.exists(pathWithGz) ){ if(SPIFFS.exists(pathWithGz)) { path += ".gz"; } File file = SPIFFS.open(path, "r"); server.streamFile(file, contentType); file.close(); return true; } return false; }
控制網頁的jQuery程式說明,請參閱書本13-8頁。
編譯並上傳主程式之後,使用瀏覽器開啟“jarvis.local”,即可看到和書本13-8頁相同的網頁和操作模式。
老師:
檔案上傳到SPIFFS後會消失嗎?
另外,上傳網頁檔案後再燒程式碼進ESP,會顯示錯誤
我就拔掉插頭重插,就可以了,這樣做對嗎?
最後,如果對老師的書中內容有疑問,可以直接在這裡發問嗎?
hi rex:
請問錯誤訊息的內容是什麼?也請嘗試安裝新版本SPIFFS上傳工具看看。
可以,相關問題請PO在這裡。
thanks,
jeffrey
老師您好:
網頁上傳到SPIFFS後
如果要ESP8266傳送資料來改變網頁內容該怎麼處理?可否指點一下,謝謝。
跟上文一樣,程式分成用戶端和伺服器端兩部份。伺服器端程式如同12-31頁所示,透過server.send()方法送出HTML或文字資料給前端;前端網頁可採用jQuery程式庫對伺服器端程式請求資料,再動態拼湊成網頁。
thanks,
jeffrey
不好意思請問一下 在ESP8266的SPIFFS檔案系統存放網頁檔案這邊使用esp8266 那我手邊只有arduino yun板也能做到類似這篇得實驗嗎
可以,據我了解Yun也能安裝Node.js,但是我沒用過Yun。
thanks,
jeffrey
Hello Mr.Cubie,
I’ve tried to establish my own webserver using your methods,and I found out that it worked pretty well on phones,while when visited by firefox, I got a bunch of LmacRxBlk:1 errors on the serial output. And I tried to analyse it with fiddler and I found that all the response of requests of images were 404.
I guess that is because the brouser is requesting too frequently even when the 8266 is sending stream files.
I am wondering if you can help me out .
Thanks
其实你可以直接用简体中文留言 🙂
如同你的推测,造成 LmacRxBlk:1 错误的原因是浏览器的连线超出ESP8266的负荷。
ESP8266只能同时应付5个连线请求,然而,浏览器在读取网页时,会同时向后台发起不同资源(.html, .css, .js, .png,…)的请求,导致ESP8266崩溃。
你可以尝试把CSS和JavaScript嵌入HTML,也把所有图片转成base64编码字元(这是免费的线上图像base64转换工具),直接嵌入HTML。如此一来,每次连线时,都只会有一个连线请求。
或者,请尝试改用ESPAsyncWebServer,我尚未尝试过,不过,根据此项目网页的描述,它能应付同时多个连线请求,而且运行速度飞快。
thanks,
jeffrey
非常感谢!诚然如您所说,目前我能在github上找到的解决方案就只有这两种。我已经下载了那个github的async web server的arduino库,正在学习使用。
Thanks
您好,我已经使用成功esp async web server 这个库,并且非常建议您尝试一下,连接稳定,速度非常快!
Regards.
感谢告知,我下周会尝试。
thanks,
jeffrey
老師您好:
想請問一下 把網頁上傳到SPIFF後 要怎麼對網頁進行控制
我用的板子是NodeMCU 程式是用ESP8266WebServer資料庫
我的網頁是控制開關 在按下開後要輸出一個高電位的電壓這樣
ON 開
要怎麼對這行進行控制
請參閱12-30頁「處理GET或POST請求」單元。
thanks,
jeffrey
您好,以這個範例來做改變,當我增加一組開關時就無法動作了,請問這樣是哪裡的問題呢??
大概是程式邏輯的問題吧。
thanks,
jeffrey
老師您好,對於網路並不是很了解,有些問題想請教
sever.on()方法是傳入一個路徑的字元陣列,以及函式指標(?)的Handler function名稱
在根據Handler內寫的sever.send()或者server.streamFile()方法,在用戶端請求的時候回傳網頁資源給用戶,這樣理解對嗎?
這樣的話根據\”在ESP8266的SPIFFS檔案系統存放網頁檔案(一)\”的程式,在54、55行都有在on()的時候呼叫streamFile()對吧? 但是本篇文章卻只有.onNotFound()的時候,有去呼叫handleFileRead(),裡面才有去呼叫streamFile(), 我的問題是一般用戶端請求時,伺服器是如何知道他有哪些網頁資源的呢?
伺服器並不知道有哪些路徑可用,它是收到用戶端的請求之後,再去比對指定路徑的資源是否存在。
thanks,
jeffrey