{"id":21528248,"url":"https://github.com/hrassi/esp32_sdcard_filebrowsing_server","last_synced_at":"2025-06-14T18:36:51.065Z","repository":{"id":262081193,"uuid":"886166794","full_name":"hrassi/esp32_sdcard_FileBrowsing_server","owner":"hrassi","description":"micropython web interface to browse files and view images stored on an SD card connected to an ESP32.","archived":false,"fork":false,"pushed_at":"2024-11-10T11:43:56.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-24T06:09:37.290Z","etag":null,"topics":["esp32-sdcard-server","esp32-server","server"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hrassi.png","metadata":{"files":{"readme":"README.txt","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2024-11-10T11:35:50.000Z","updated_at":"2024-11-10T11:45:12.000Z","dependencies_parsed_at":"2024-11-10T12:41:30.698Z","dependency_job_id":null,"html_url":"https://github.com/hrassi/esp32_sdcard_FileBrowsing_server","commit_stats":null,"previous_names":["hrassi/esp32_sdcard_filebrowsing_server"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrassi%2Fesp32_sdcard_FileBrowsing_server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrassi%2Fesp32_sdcard_FileBrowsing_server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrassi%2Fesp32_sdcard_FileBrowsing_server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hrassi%2Fesp32_sdcard_FileBrowsing_server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hrassi","download_url":"https://codeload.github.com/hrassi/esp32_sdcard_FileBrowsing_server/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244091761,"owners_count":20396667,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["esp32-sdcard-server","esp32-server","server"],"created_at":"2024-11-24T01:52:21.879Z","updated_at":"2025-03-17T18:44:47.655Z","avatar_url":"https://github.com/hrassi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"How it Works:\nThe ESP32 acts as a simple HTTP server that clients (like your phone or computer) can connect to via Wi-Fi.\nThe server serves both directory listings and image files stored on the SD card.\nClients can click on folders to navigate through the SD card, and clicking on image files opens them directly in the browser.\nIn essence, this script provides a very basic web interface to browse files and view images stored on an SD card connected to an ESP32.\n\n\n1. Access Point Setup\nap = network.WLAN(network.AP_IF)\nap.active(True)\nap.config(essid=\"sam\", password=\"12345678\")\nnetwork.WLAN(network.AP_IF): Initializes the ESP32 as an Access Point (AP), allowing devices to connect to it like a Wi-Fi router.\nap.active(True): Activates the access point.\nap.config(essid=\"sam\", password=\"12345678\"): Configures the access point with an SSID (sam) and password (12345678).\nThe script waits for the Access Point to become active, then prints the IP address (ap.ifconfig()[0]) that clients (like your phone or computer) can use to connect to the ESP32.\n\n2. SD Card Initialization\nspi = SPI(1, baudrate=1000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19))\ncs = Pin(5, Pin.OUT)\nsd = sdcard.SDCard(spi, cs)\nvfs = os.VfsFat(sd)\nos.mount(vfs, \"/sd\")\nSPI Initialization: Sets up the SPI bus to communicate with the SD card. The SPI pins (SCK, MOSI, and MISO) are configured along with the baud rate. These pins (18, 23, and 19) are the hardware SPI pins on the ESP32.\nsdcard.SDCard(spi, cs): Initializes the SD card using the SPI interface and the Chip Select (CS) pin.\nos.VfsFat(sd): Creates a virtual file system (VFS) over the SD card, allowing access to files on the SD card using regular file system functions.\nos.mount(vfs, \"/sd\"): Mounts the virtual file system at /sd, making it accessible like any other directory in the file system.\nThis setup ensures that the ESP32 can access and read from the SD card.\n\n3. list_files Function\ndef list_files(path):\n    if path == \"/\":\n        path = \"/sd\"\n    \n    html = \"\"\"\n    \u003chtml\u003e\n    \u003chead\u003e\u003ctitle\u003eSD Card Browser\u003c/title\u003e\u003c/head\u003e\n    \u003cbody\u003e\n        \u003ch1\u003eSD Card Files\u003c/h1\u003e\n        \u003cul\u003e\n    \"\"\"\nThe list_files function generates an HTML page that lists all files and directories in the given path.\nIf the requested path is the root (\"/\"), it defaults to the /sd directory.\n    if path != \"/sd\":\n        parent_path = \"/\".join(path.rstrip(\"/\").split(\"/\")[:-1]) or \"/sd\"\n        html += f\"\u003cli\u003e\u003ca href='?path={parent_path}'\u003e[Back]\u003c/a\u003e\u003c/li\u003e\"\nIf the path is not the root (/sd), a \"Back\" link is generated to navigate to the parent directory.\n    for item in os.listdir(path):\n        if item.startswith(\".\"):\n            continue\n        item_path = f\"{path}/{item}\"\n        \n        if os.stat(item_path)[0] \u0026 0x4000:  # Directory\n            html += f\"\u003cli\u003e\u003ca href='?path={item_path}'\u003e{item}/\u003c/a\u003e\u003c/li\u003e\"\n        else:\n            html += f\"\u003cli\u003e\u003ca href='?path={item_path}'\u003e{item}\u003c/a\u003e\u003c/li\u003e\"\n    \n    html += \"\u003c/ul\u003e\u003c/body\u003e\u003c/html\u003e\"\n    return html\nos.listdir(path): Lists all files and directories in the given path.\nos.stat(item_path): Retrieves file stats. The 0x4000 check identifies whether an item is a directory (directories return this flag in the first byte of their status).\nFor directories, a link is generated to browse the folder. For files, a link is generated to open or download the file.\nThe HTML structure is returned, forming the list of files and folders.\n4. serve_file Function\ndef serve_file(cl, path):\n    try:\n        if path.endswith(\".jpg\") or path.endswith(\".jpeg\"):\n            content_type = \"image/jpeg\"\n        elif path.endswith(\".png\"):\n            content_type = \"image/png\"\n        elif path.endswith(\".gif\"):\n            content_type = \"image/gif\"\n        else:\n            content_type = \"text/plain\"\n\n        cl.send(f\"HTTP/1.1 200 OK\\r\\nContent-Type: {content_type}\\r\\n\\r\\n\".encode())\nserve_file handles serving image files.\nThe function checks the file extension (.jpg, .png, .gif) to determine the correct content type for the file (used in the HTTP response headers).\n        with open(path, \"rb\") as f:\n            while True:\n                data = f.read(1024)\n                if not data:\n                    break\n                cl.send(data)\nopen(path, \"rb\"): Opens the file in binary read mode (\"rb\").\nThe file is read in chunks of 1024 bytes and sent over the socket to the client.\n    except Exception as e:\n        print(f\"Failed to serve file {path}: {e}\")\n        cl.send(b\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\")\nIf an error occurs while reading or sending the file, a 404 Not Found response is sent to the client.\n5. serve_page Function (Main Request Handling)\ndef serve_page():\n    addr = socket.getaddrinfo(\"0.0.0.0\", 80)[0][-1]\n    s = socket.socket()\n    s.bind(addr)\n    s.listen(1)\n    print(\"Server listening on:\", addr)\nThe server listens on all available network interfaces (0.0.0.0) and port 80 for HTTP connections.\nsocket.getaddrinfo() retrieves address information (IP address and port).\ns.bind() binds the server to the IP address and port.\ns.listen(1) prepares the server to listen for incoming connections (with a backlog of 1 client).\n    while True:\n        cl, addr = s.accept()\n        print(\"Client connected from:\", addr)\n        cl_file = cl.makefile(\"rwb\", 0)\n        request_line = cl_file.readline().decode()\ns.accept(): Accepts a new incoming connection from a client.\ncl.makefile(\"rwb\", 0): Creates a file-like object for the client socket to read and write data.\nrequest_line = cl_file.readline().decode(): Reads the first line of the HTTP request (which contains the requested URL).\n        path = \"/sd\"\n        if \"?\" in request_line:\n            try:\n                query = request_line.split()[1].split(\"?\")[1]\n                for param in query.split(\"\u0026\"):\n                    if param.startswith(\"path=\"):\n                        path = param.split(\"=\")[1]\n                        if path == \"\":\n                            path = \"/sd\"\n            except Exception as e:\n                print(f\"Error parsing path: {e}\")\nIf the URL contains a query (e.g., ?path=/sd/images), the path is extracted from the query string.\n        try:\n            if not os.stat(path)[0] \u0026 0x4000:\n                serve_file(cl, path)\n            else:\n                response = f\"HTTP/1.1 200 OK\\r\\nContent-Type: text/html\\r\\n\\r\\n{list_files(path)}\"\n                cl.send(response.encode())\nos.stat(path)[0] \u0026 0x4000: Checks whether the requested path is a file or a directory.\nIf it's a file, the serve_file() function is called to serve the file.\nIf it's a directory, the list_files() function is called to display the list of files and directories.\n        except OSError:\n            cl.send(b\"HTTP/1.1 404 Not Found\\r\\n\\r\\n\")\n        \n        cl.close()\nIf the requested path does not exist, a 404 Not Found response is sent to the client.\ncl.close() closes the client connection after handling the request.\n6. Running the Server\nserve_page()\nserve_page() is called to start the server, and it runs in an infinite loop to handle incoming client requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhrassi%2Fesp32_sdcard_filebrowsing_server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhrassi%2Fesp32_sdcard_filebrowsing_server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhrassi%2Fesp32_sdcard_filebrowsing_server/lists"}