135 keer bekeken / views
Dit is het derde deel van drie posts over drie bibliotheken die ik heb geschreven om ons leven makkelijker te maken:
- Deel 1: Networking
- Deel 2: Single Page Application (de GUI)
- Deel 3: Filesystem Manager
Dit is het 3e deel en gaat dus over de Filesystem Manager.
In mijn eerdere posts heb ik besproken hoe bibliotheken het leven van een ontwikkelaar kunnen vereenvoudigen. In dit derde deel richt ik me specifieke op de FSmanager bibliotheek. Deze bibliotheek biedt een eenvoudige manier om het bestandssysteem op ESP8266- en ESP32-microcontrollers te beheren via een webinterface.
Wat is FSmanager?
FSmanager is een C++-bibliotheek die gebruikmaakt van LittleFS om bestandssystemen op ESP-microcontrollers te beheren. Met FSmanager kun je bestanden uploaden, downloaden, verwijderen en mappen aanmaken of verwijderen. Daarnaast biedt het functies om de totale en gebruikte opslagruimte te tonen. De bibliotheek is ontworpen voor zowel ESP8266 als ESP32 en integreert naadloos met de Arduino-ontwikkelomgeving.
Belangrijkste functies
- Bestandsbeheer: Uploaden, downloaden en verwijderen van bestanden.
- Mapbeheer: Aanmaken en verwijderen van mappen (let op: alleen lege mappen kunnen worden verwijderd).
- Opslaginformatie: Weergave van totale en gebruikte opslagruimte, met automatische aanpassing van de eenheden (B, KB, MB).
- Systeembestandenbescherming: Voorkomt per ongeluk verwijderen van cruciale systeembestanden.
Installatie en gebruik
Voor PlatformIO-gebruikers:
Voeg de FSmanager-bibliotheek toe aan je platformio.ini-bestand:
lib_deps = https://github.com/mrWheel/esp-fsmanager
Zorg ervoor dat de benodigde afhankelijkheden, zoals LittleFS en de juiste webserverbibliotheek voor je microcontroller, zijn geïnstalleerd.
Voor Arduino IDE-gebruikers:
- Download de FSmanager-bibliotheek als een .zip-bestand van de GitHub-pagina.
- Open de Arduino IDE en selecteer Sketch > Add .ZIP Library….
- Navigeer naar de locatie waar je het .zip-bestand hebt opgeslagen en voeg het toe.
- Installeer de benodigde afhankelijkheden via de Bibliotheekbeheerder:
* Voor ESP8266: ESP8266WebServer en LittleFS.
* Voor ESP32: WebServer en LittleFS.
Voorbeeld van gebruik
Hier is een eenvoudig voorbeeld van hoe je FSmanager in je project kunt integreren:
#include <FSmanager.h>; void setup() { Serial.begin(115200); //-- Initialize WiFiManager wifiManager.autoConnect("FSManager-AP"); LittleFS.begin(); fsManager.begin(&Serial); fsManager.addSystemFile("/basicFSM.html"); fsManager.addSystemFile("/basicFSM.js"); server.on("/", HTTP_GET, []() { server.send(200, "text/html", readSystemHtml("/basicFSM.html")); }); server.onNotFound([]() { Serial.printf("Not Found: %s\n", server.uri().c_str()); server.send(404, "text/plain", "404 Not Found"); }); server.begin(); Serial.println("Webserver started!"); } void loop() { server.handleClient(); }
Dit voorbeeld initialiseert FSmanager en start de webinterface, waardoor je via een webbrowser toegang krijgt tot het bestandssysteem van je ESP-microcontroller. Om een werkende FSmanager te krijgen moet je er wel voor zorgen dat de bestanden basicFSM.html
en basicFSM.js
bestaan in de root van het LittleFS!
Het basicFSM.js
bestand beval alle Javascript functies die nodig zijn voor de werking van de FSmanager. Het basicFSM.html
bestand ziet er zo uit:
<!DOCTYPE html> <html> <head> <title>FSManager</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>FileSystem Manager</h1> <div id="fileList"> <h2>Files</h2> <div id="files"></div> <div id="spaceInfo"></div> </div> <div style="display: gap: 20px; margin-bottom: 20px;"> <div> <h2 id="uploadHeading">Upload File</h2> <form id="uploadForm" action="/fsm/upload" method="post" enctype="multipart/form-data" onsubmit="handleUpload(event)"> <input type="file" name="file" required> <button type="submit" class="button upload">Upload File</button> </form> </div> <div id="folderInput"> <h2>New Folder</h2> <div style="display: gap: 10px;"> <input type="text" id="foldername" placeholder="Enter folder name"> <button class="button" id="createFolderBtn" onclick="createFolder()">Create</button> </div> </div> </div> <div id="status"></div> <script src="/basicFSM.js"></script> </body> </html>
Het belangrijkste onderdeel is:
<div id="fileList"> <h2>Files</h2> <div id="files"></div> <div id="spaceInfo"></div> </div>
In de <div>
met id="fileList"
zullen de mappen en bestanden van het LittleFS worden ingevuld en meer specifiek in de <div>
met id="files"
. In de <div>
met id="spaceInfo"
komen de totale grootte en de gebruikte ruimte van het LittelFS te staan.
Onder deze <div>
‘s komen twee knoppen. Deze dienen respectievelijk voor het uploaden van een bestand naar de ESP:
<div> <h2 id="uploadHeading">Upload File</h2> <form id="uploadForm" action="/fsm/upload" method="post" enctype="multipart/form-data" onsubmit="handleUpload(event)"> <input type="file" name="file" required> <button type="submit" class="button upload">Upload File</button> </form> </div>
en voor het aanmaken van een nieuwe map.
<div id="folderInput"> <h2>New Folder</h2> <div style="display: gap: 10px;"> <input type="text" id="foldername" placeholder="Enter folder name"> <button class="button" id="createFolderBtn" onclick="createFolder()">Create</button> </div> </div>
Het mag duidelijk zijn dat de gebruikte id
‘s correct in het html
bestand moeten staan omdat de Javascript functies anders niet werken.
Als je mij wil helpen om meer van dit soort posts te schrijven, overweeg dan om een kleine donatie te geven door op de knop hieronder te klikken.
FSmanager vereenvoudigt het beheer van het bestandssysteem op ESP8266- en ESP32-microcontrollers aanzienlijk. Door een intuïtieve webinterface te bieden, maakt het de interactie met bestanden en mappen op je apparaat eenvoudig en efficiënt. Of je nu bestanden wilt uploaden, verwijderen of de opslagruimte wilt controleren, FSmanager is het tool dat je hierbij helpt.
API Reference
Overview
De FSmanager-bibliotheek biedt een webgebaseerd bestandsbeheersysteem voor ESP32- en ESP8266-microcontrollers. Hiermee kunnen gebruikers bestanden in het LittleFS-bestandssysteem via een webinterface bekijken, uploaden, downloaden en beheren. De bibliotheek is ontworpen om te werken met zowel ESP32 als ESP8266 en past zich automatisch aan de juiste platformspecifieke API’s aan.
Class: FSmanager
Description
De FSmanager-klasse integreert met een ESP-webserver om bestandsbeheerfunctionaliteit te bieden. Het behandelt bestandsbewerkingen zoals het weergeven, uploaden, downloaden en verwijderen van bestanden, evenals het aanmaken en verwijderen van mappen.
Constructor
FSmanager(WebServerClass &server);
Aanmaken van een FSmanager-instantie
Maakt een nieuwe FSmanager-instantie aan.
Parameters:
- server: Referentie naar een WebServer-instantie (WebServer voor ESP32 of ESP8266WebServer voor ESP8266).
Voorbeeld:
#ifdef ESP32 WebServer server(80); #else ESP8266WebServer server(80); #endif FSmanager fsManager(server);
Publieke methoden
begin
void begin(Stream* debugOutput = &Serial);
Initialiseert FSmanager en stelt de benodigde HTTP-handlers in voor bestandsbeheer.
Parameters:
• debugOutput: Optionele Stream* voor debug-uitvoer (standaard: Serial).
Voorbeeld:
void setup() { Serial.begin(115200); LittleFS.begin(); //-- Initialiseren met debug-uitvoer naar Serial fsManager.begin(&Serial); server.begin(); }
setSystemFilePath
void setSystemFilePath(const std::string &path);
Stelt het pad in voor systeembestanden, die worden beschermd tegen verwijdering.
Parameters:
- path: Pad voor systeembestanden (wordt genormaliseerd zodat het altijd begint met ‘/’ en nooit eindigt met ‘/’).
Voorbeeld:
//-- Stel het pad voor systeembestanden in op "/config" fsManager.setSystemFilePath("/config"); //-- Bestanden toegevoegd met addSystemFile zijn nu relatief aan dit pad fsManager.addSystemFile(fsManager.getSystemFilePath() + "/settings.json");
getSystemFilePath
std::string getSystemFilePath() const;
Geeft het huidige pad voor systeembestanden terug.
Returnwaarde:
- Het huidige systeembestandspad als een std::string.
Voorbeeld:
//-- Haal het huidige systeembestandspad op std::string sysPath = fsManager.getSystemFilePath(); Serial.printf("Huidig systeem pad: %s\n", sysPath.c_str()); //-- Gebruik het om een volledig pad te maken std::string fullPath = sysPath + "/config.json";
addSystemFile
void addSystemFile(const std::string &fileName, bool setServe = true);
Voegt een bestand toe aan de lijst met systeembestanden (wordt beschermd tegen verwijdering via de webinterface).
Parameters:
- fileName: Het pad naar het bestand dat als systeembestand moet worden toegevoegd.
- setServe: (Optioneel) true om het bestand automatisch te serveren via de webserver (standaard: true).
Voorbeeld:
//-- Voeg "index.html" toe als systeembestand en serveer het fsManager.addSystemFile("/index.html"); //-- Voeg een configuratiebestand toe als systeembestand, maar serveer het niet fsManager.addSystemFile("/config/settings.json", false); //-- Voeg een bestand toe relatief aan het systeempad fsManager.setSystemFilePath("/app"); fsManager.addSystemFile(fsManager.getSystemFilePath() + "/app.js");
getCurrentFolder
std::string getCurrentFolder();
Geeft het huidige pad terug van de map die wordt bekeken in de file manager.
Returnwaarde:
- Het huidige map-pad als een std::string.
Voorbeeld:
//-- Haal de huidige map op std::string currentFolder = fsManager.getCurrentFolder(); Serial.printf("Momenteel in map: %s\n", currentFolder.c_str()); //-- Controleer of we in de rootmap zijn if (currentFolder == "/") { Serial.println("In de rootmap"); }
Private methoden (voor begrip van de werking)
Hoewel deze methoden privé zijn en niet direct toegankelijk, helpt het begrijpen ervan bij het effectief gebruiken van de bibliotheek:
- handleFileList – Behandelt HTTP-verzoeken om bestanden en mappen in een specifieke map weer te geven.
- handleDelete – Behandelt HTTP-verzoeken om een bestand te verwijderen.
- handleUpload – Behandelt HTTP-bestandsuploadverzoeken.
- handleDownload – Behandelt HTTP-verzoeken om een bestand te downloaden.
- handleCreateFolder – Behandelt HTTP-verzoeken om een nieuwe map aan te maken.
- handleDeleteFolder – Behandelt HTTP-verzoeken om een map te verwijderen.
- formatSize – Formatteert een bestandsgrootte in bytes naar een leesbaar formaat (B, KB, MB).
- isSystemFile – Controleert of een bestand een systeembestand is (beschermd tegen verwijdering).
- getTotalSpace – Geeft de totale beschikbare opslagruimte terug.
- getUsedSpace – Geeft de gebruikte opslagruimte terug.
- handleCheckSpace – Behandelt HTTP-verzoeken om te controleren of er voldoende ruimte is voor een upload.
Volledig gebruiksvoorbeeld
Hier is een compleet voorbeeld van hoe je FSmanager kunt instellen en gebruiken:
#include <Arduino.h> #include <WiFiManager.h> #ifdef ESP32 #include <WebServer.h> #include <Update.h> #else #include <ESP8266WebServer.h> #include <ESP8266HTTPUpdate.h> #endif #include <FSmanager.h> WiFiManager wifiManager; Stream* debug = nullptr; #ifdef ESP32 WebServer server(80); #else ESP8266WebServer server(80); #endif FSmanager fsManager(server); #include <LittleFS.h> void handleFileRequest(String path) { //-- First try with systemPath if available std::string sysPath = fsManager.getSystemFilePath(); String fullPath; if (!sysPath.empty() && sysPath.back() == '/') { sysPath.pop_back(); } Serial.printf("handleFileRequest(): sysPath[%s], path[%s]\n", sysPath.c_str(), path.c_str()); if (sysPath.empty()) fullPath = path; else fullPath = (sysPath + path.c_str()).c_str(); Serial.printf("handleFileRequest(): fullPath[%s]\n", fullPath.c_str()); if (LittleFS.exists(fullPath)) { File file = LittleFS.open(fullPath, "r"); //-- Determine the correct MIME type based on file extension String contentType = "text/plain"; //-- Default if (fullPath.endsWith(".html")) contentType = "text/html"; else if (fullPath.endsWith(".css")) contentType = "text/css"; else if (fullPath.endsWith(".js")) contentType = "application/javascript"; else if (fullPath.endsWith(".png")) contentType = "image/png"; else if (fullPath.endsWith(".jpg") || fullPath.endsWith(".jpeg")) contentType = "image/jpeg"; else if (fullPath.endsWith(".gif")) contentType = "image/gif"; else if (fullPath.endsWith(".ico")) contentType = "image/x-icon"; else if (fullPath.endsWith(".svg")) contentType = "image/svg+xml"; else if (fullPath.endsWith(".woff")) contentType = "font/woff"; else if (fullPath.endsWith(".woff2")) contentType = "font/woff2"; else if (fullPath.endsWith(".ttf")) contentType = "font/ttf"; else if (fullPath.endsWith(".eot")) contentType = "text/plain"; else if (fullPath.endsWith(".json")) contentType = "application/json"; Serial.printf("handleFileRequest: [%s] contentType[%s]\n", fullPath.c_str(), contentType.c_str()); //-- Send the file with the correct content type server.streamFile(file, contentType); file.close(); return; } else { server.send(404, "text/plain", "File Not Found"); } } // handleFileRequest() String readSystemHtml(const char* htmlFile) { //-- First try with systemPath if available std::string sysPath = fsManager.getSystemFilePath(); File file; if (!sysPath.empty()) { std::string fullPath = sysPath + htmlFile; file = LittleFS.open(fullPath.c_str(), "r"); } //-- If file not found with systemPath or systemPath is empty, try original path if (!file) { file = LittleFS.open(htmlFile, "r"); } if (!file) { Serial.println("Failed to open file for reading"); //-- Return empty string if file not found return String(); } String fileContent; while (file.available()) { //-- Read byte by byte and append to String fileContent += (char)file.read(); } file.close(); return fileContent; } // readSystemHtml() void setup() { Serial.begin(115200); //-- Initialize WiFiManager wifiManager.autoConnect("fancyFSM-AP"); LittleFS.begin(); fsManager.begin(&Serial); fsManager.addSystemFile("/index.html"); fsManager.addSystemFile("/favicon.ico"); fsManager.setSystemFilePath("/fancyFSM"); fsManager.addSystemFile(fsManager.getSystemFilePath() + "/fancyFSM.html"); fsManager.addSystemFile(fsManager.getSystemFilePath() + "/fancyFSM.js"); fsManager.addSystemFile(fsManager.getSystemFilePath() + "/fancyFSM.css"); server.on("/", HTTP_GET, []() { server.send(200, "text/html", readSystemHtml("/fancyFSM.html")); }); server.onNotFound([]() { Serial.printf("Not Found: %s\n", server.uri().c_str()); server.send(404, "text/plain", "404 Not Found"); }); server.begin(); Serial.println("Webserver started!"); } void loop() { server.handleClient(); }
Dit voorbeeld gaat er van uit dat er drie bestanden in de map fancyFSM
staan
- fancyFSM.html
- fancyFSM.css
- fancyFSM.js
Examples
Alle in deze post gepresenteerde code staat in de examples folder van de github repository.
Webinterface API-endpoints
De FSmanager stelt de volgende HTTP-endpoints in:
Endpoint | Methode | Beschrijving |
---|---|---|
/fsm/filelist | GET | Lijst met bestanden in een map ophalen |
/fsm/delete | POST | Bestand verwijderen |
/fsm/upload | POST | Bestand uploaden |
/fsm/download | GET | Bestand downloaden |
/fsm/checkSpace | GET | Controleren of er voldoende ruimte is voor een upload |
/fsm/createFolder | POST | Nieuwe map aanmaken |
/fsm/deleteFolder | POST | Map verwijderen |