{"id":29448652,"url":"https://github.com/trip5/espfileupdater","last_synced_at":"2026-02-08T11:03:28.940Z","repository":{"id":302188163,"uuid":"1009054301","full_name":"trip5/ESPFileUpdater","owner":"trip5","description":"A library to help automatically update and download files to an ESP's file system","archived":false,"fork":false,"pushed_at":"2026-02-02T02:14:33.000Z","size":34,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-02T11:53:25.091Z","etag":null,"topics":["arduino","arduino-library","esp32","esp32-arduino","esp8266","esp8266-arduino","file-downloader","file-updater"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trip5.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-26T13:59:19.000Z","updated_at":"2026-02-02T02:14:37.000Z","dependencies_parsed_at":"2025-07-01T03:36:28.675Z","dependency_job_id":"dab442f0-731e-4721-9b56-c831790d5ce5","html_url":"https://github.com/trip5/ESPFileUpdater","commit_stats":null,"previous_names":["trip5/espfileupdater"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/trip5/ESPFileUpdater","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trip5%2FESPFileUpdater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trip5%2FESPFileUpdater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trip5%2FESPFileUpdater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trip5%2FESPFileUpdater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trip5","download_url":"https://codeload.github.com/trip5/ESPFileUpdater/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trip5%2FESPFileUpdater/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29228552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T09:43:19.170Z","status":"ssl_error","status_checked_at":"2026-02-08T09:42:55.556Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","arduino-library","esp32","esp32-arduino","esp8266","esp8266-arduino","file-downloader","file-updater"],"created_at":"2025-07-13T19:01:50.877Z","updated_at":"2026-02-08T11:03:28.934Z","avatar_url":"https://github.com/trip5.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ESPFileUpdater Library\n\n## Overview\nThe ESPFileUpdater library provides functionality for checking and updating files from a remote server on ESP32/ESP8266 devices. It simplifies the process of managing file updates by handling metadata, calculating file hashes, and ensuring that the local files are up-to-date with the remote versions.\n\n### Features\n- Check if a remote file is newer than the local version\n- Download updates if available\n- Manage metadata files to track last modified time and file hashes\n- Support for max age checks to prevent unnecessary updates\n- Will download even if local file missing\n- Compatible with SPIFFS (tested) and LittleFS (untested)\n- Follows 3xx redirects\n\n### PlatformIO\nYour platformio.ini should contain:\n```\nlib_deps =\n  trip5/ESPFileUpdater@^1.2.0\n```\n\n### Installation\nTo install the ESPFileUpdater library, follow these steps:\n1. Download the library from the repository.\n2. Extract the contents to your Arduino libraries folder (usually located in `Documents/Arduino/libraries`).\n3. Restart the Arduino IDE to recognize the new library.\n\n### Dependent on Internet, File System, and System Time\n- It depends on an Internet connection, file system, and system time.\n- Only run it after the these 3 process are stable (usually).\n- If system time is not available at the time it runs, it will download the file only if it does not already exist on the file system.\n\n---\n\n## Usage\nTo use the ESPFileUpdater library in your project, include the header file and create an instance of the `ESPFileUpdater` class. Here is a basic example:\n\n```cpp\n#include \u003cWiFi.h\u003e\n#include \u003cSPIFFS.h\u003e\n#include \u003cESPFileUpdater.h\u003e\n\n// WiFi credentials\nconst char* ssid = \"YOUR_SSID\";\nconst char* password = \"YOUR_PASSWORD\";\n\nvoid setup() {\n    Serial.begin(115200);\n    SPIFFS.begin(true);\n    WiFi.begin(ssid, password);\n    \n    // Wait for connection\n    while (WiFi.status() != WL_CONNECTED) {\n        delay(500);\n        Serial.print(\".\");\n    }\n    Serial.println(\"WiFi connected!\");\n\n    // Set system time via SNTP\n    configTime(0, 0, \"pool.ntp.org\", \"time.nist.gov\");\n    Serial.print(\"Waiting for NTP time sync\");\n    time_t now = time(nullptr);\n    while (now \u003c 8 * 3600 * 2) {\n        delay(500);\n        Serial.print(\".\");\n        now = time(nullptr);\n    }\n    Serial.println(\" Time synchronized!\");\n\n    ESPFileUpdater updater(SPIFFS);\n    updater.setTimeout(5000);\n    ESPFileUpdater::UpdateStatus status = updater.checkAndUpdate(\"/path/to/local/file.txt\", \"https://example.com/remote/File.txt\", \"7d\", true);\n\n    if (status == ESPFileUpdater::UPDATED) {\n        Serial.println(\"[ESPFileUpdater: File.txt] Update completed.\");\n    } else if (status == ESPFileUpdater::NOT_MODIFIED || status == ESPFileUpdater::MAX_AGE_NOT_REACHED) {\n        Serial.println(\"[ESPFileUpdater: File.txt] No update needed.\");\n    } else {\n        Serial.println(\"[ESPFileUpdater: File.txt] Update failed.\");\n    }\n}\n\nvoid loop() {\n    // Your main code here\n}\n```\n---\n## Syntax\n\n`ESPFileUpdater::UpdateStatus status = updater.checkAndUpdate(\"/local/file\", \"https://remote/file\", \"maxAge\", verbose);`\n\n### Mandatory\n\n`/local/file` : path and file on the file system - probably best to start with root `/`.\n\n`https://remote/file` : try to use a URL that doesn't do a re-direct - see the FreeRTOS_Task example for a Github retrieval.\n\n### Options\n\n`maxAge`: can accept `X hours`, `X days`, `X weeks`, `X months` as an argument.\nIf the file does not exist or `maxAge` is not specified, it will download/update immediately, without any checks.\nIf `maxAge` is not specified or is empty, then file information will not be saved to a .meta file (it simply downloads the file).\nYou may use abbreviations like `hr` or `h` or `d` or `wk` or `w` or `mo` or `m`, with or without spaces, with or without `s`.\nAlthough the process can be called often, it will not update if the accompanying .meta file has a date-stamp within that window of time.\nBe reasonable. Don't check for updates too frequently.\nIf you need to update often, specify `0d` to at least check if the remote file is updated.\n\n`verbose`: use `true` or `false` to enable or disable verbose logging to serial.  It will update every step of the way.  Good for debugging.\nIf not specified, assumed to be false.\n\nYou may specify these options in any order, one, both, or not at all.\n\n---\n\n## Process\n- Checks local FS for file existence\n  - Waits for FS readiness\n    - If not ready 🛑 [stop]\n  - If file does not exist ✅ [update]\n    - This initial file may get 1970-01-01 as timestamp in .meta file if system time is incorrect\n  - If maxAge not specified ✅ [update]\n    - No .meta file is checked, created, or written (if one exists, it will remain)\n  - If maxAge is \"0\" ✅ [update]\n    - This initial file may get 1970-01-01 as timestamp in .meta file if system time is incorrect\n- Waits for system time to be correct\n    - If not ready 🛑 [stop]\n- Reads .meta file URL\n  - if URL is different than specified ✅ [update]\n- Reads accompanying .meta file for date\n  - If maxAge has not passed then 🛑 [stop]\n- Waits for network connection readiness\n    - If not ready 🛑 [stop]\n- Attempts to retrieve date-stamp from remote file\n  - If remote file is newer ✅ [update]\n  - If remote file is not newer 🛑 [stop]\n- If the server does not support date-stamp, then stream 100KB (at most) from the remote file and generate a hash\n  - This hash is compared to a hash stored in the .meta file\n  - If hashes are the same, update the date-stamp in the meta file with the current date 🛑 [stop]\n  - If the hashes differ, assume remote file is newer ✅ [update]\n\n### Update Process\n\n- Downloads to temporary file first for safety\n- Deletes old file, renames new file\n- Hashes new file (if not already done during stream)\n- Writes accompanying .meta file\n\n### The .meta File\n\nExample\n```\nhttps://example.com/firmware.bin\n1718726400\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n```\n\n- The URL the file was last retrieved from\n- UNIX EPOCH of the last update\n- Hash\n\n---\n\n## API Reference\n\n### ESPFileUpdater Class\n- **ESPFileUpdater(fs::FS\u0026 fs)**: Constructor that initializes the updater with the specified file system.\n- **UpdateStatus checkAndUpdate(const String\u0026 localPath, const String\u0026 remoteURL, const String\u0026 maxAge)**: Checks if the remote file is newer and updates if necessary.\n\n### Settings\n\nThese can be changed.\n\n`setMaxSize(size_t bytes);` If the date comparison fails, the file will be streamed from the server (without downloading) and compared to the file on the system. This helps reduce how many bytes are needed to generate a hash for the comparison.\n100KB seems a reasonable default but you can increase or decrease the number.\n\n`setTimeout(uint32_t ms);` You should always do your best to make sure the various components needed for\nthis are ready but there are checks and timeouts as part of the routines to wait if they are ready.\nIf you have time-critical operations, check the FreeRTOS_Task folder so that the\nupdater doesn't block your other operations.  15 seconds is excessive I'm sure but it's just in case.\n\n`setUserAgent(const String\u0026 ua);` Some developers might like to know who / what program is fetching data from them.\n\n`setInsecure(bool insecure);` Enables insecure mode.  It will disable checking of secure certificates when using HTTPS connections. This may help lower memory use (not much likely).  Setting to `true` seems to make connections fail more often.\n\n`setBuffer(size_t bytes)` Sets the buffer size.  Bigger is faster.\n\n`setYieldInterval(milliseconds)` Sets after how many ms, `yield();` is executed.  Can help responsiveness. Diminishing returns below `10`. Use `0` if other processes need to be greedy.\n\n#### Stack Allocation (with defaults)\n\n```cpp\n  ESPFileUpdater updater(SPIFFS);\n  updater.setMaxSize(102400);      // 100 KB max stream size for hashing\n  updater.setTimeout(15000);       // 15000ms / 15s for timeout (for each check)\n  updater.setUserAgent(\"MyESPProject/1.2.3 (https://github.com/me/MyESPProject)\");\n  updater.setInsecure(false);      // insecure mode enabled\n  updater.setBuffer(2048);\n  updater.setYieldInterval(20);\n```\n\n#### Heap Allocation\n\n```cpp\n  ESPFileUpdater* updater = nullptr;\n  updater = new ESPFileUpdater(SPIFFS);\n  updater-\u003esetMaxSize(102400);\n  updater-\u003esetTimeout(15000);\n  updater-\u003esetUserAgent(\"MyESPProject/1.2.3 (https://github.com/me/MyESPProject)\");\n  updater-\u003esetInsecure(false);\n  updater-\u003esetBuffer(2048);\n  updater-\u003esetYieldInterval(20);\n```\n\n### UpdateStatus Enum\n\n- **UPDATED**: Indicates that the file was updated successfully.\n- **MAX_AGE_NOT_REACHED**: Indicates that the maximum age for updates has not been reached.\n- **NOT_MODIFIED**: Indicates that the remote file has not been modified.\n- **SERVER_ERROR**: Indicates that there was an error connecting to the server.\n- **FILE_NOT_FOUND**: Indicates that the remote file was not found.\n- **FS_ERROR**: Indicates an error with the SPIFFS file system.\n- **TIME_ERROR**: Indicates that system time was not set.\n- **NETWORK_ERROR**: Indicates the network connect was not ready.\n- **CONNECTION_FAILED**: Indicates a connection error; error returned by the upstream library will be shown if verbose is on.\n---\n\n## SPIFFS Limitations\n\nKeep in mind file names (including path) must be 31 characters or less.\nBecause of this limitation and the fact this library adds\nextra extensions to the .meta and .tmp download files,\nthe real usable file name length limit is 27 characters!\n\nI'm not sure about LittleFS limitations.\n\n---\n\n## Examples\n\nCheck the `examples` folder for examples of how to use the ESPFileUpdater library in your projects.\n\n---\n\n## Update History\n\n| Date       | Version | Release Notes             |\n| ---------- | ------- |-------------------------- |\n| 2026.02.08 | 1.2.0   | Handles chunked transfers properly |\n| 2026.02.04 | 1.1.2   | PlatformIO examples and readme fixed |\n| 2026.02.03 | 1.1.1   | PlatformIO release        |\n| 2025.07.20 | 1.1.0   | Settings added            |\n| 2025.06.29 | 1.0.0   | First release             |\n\n---\n\n## License\n\nThis library is released under the MIT License. See the LICENSE file for more details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrip5%2Fespfileupdater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrip5%2Fespfileupdater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrip5%2Fespfileupdater/lists"}