ESP32 008 MicroPython Web框架庫 Microdot 實現的網絡文件服務器

在這里插入圖片描述

  • 以下是整合了所有功能的完整 main.py(在ESP32 007 MicroPython 適用于 Python 和 MicroPython 的小型 Web 框架庫 Microdot基礎上),實現了:
    • Wi?Fi 自動連接(支持靜態 IP);
    • SD 卡掛載;
    • /sd/www/ 讀取 HTML 和靜態文件
    • 瀏覽器瀏覽 /files 自動列出 SD 卡根目錄文件并提供下載鏈接
    • 通過 /download/ 路由下載文件
    • 通過 /upload/ 路由上傳文件
#from lib.microdot import Microdot, Response
from microdot import Microdot, Response , redirect
from wifi import connect_wifi
from scard import SDCard
from machine import SPI, Pin
import os#  替代  if os.path.isfile(full_path_www):
def is_file(path):try:return not (os.stat(path)[0] & 0x4000)  # 非目錄except:return False
# 掛載 SD 卡
def mount_sd():try:spi = SPI(2, baudrate=1_000_000,sck=Pin(5),mosi=Pin(6),miso=Pin(7))cs = Pin(4, Pin.OUT)sd = SDCard(spi, cs)os.mount(sd, '/sd')print("? SD 卡掛載成功:", os.listdir('/sd'))return Trueexcept Exception as e:print("? SD 卡掛載失敗:", e)return False# 啟動網絡與文件系統
connect_wifi()
mount_sd()Response.default_content_type = 'text/html'
app = Microdot()# 根目錄 —— 加載 /sd/www/index.html
@app.route('/')
def index(req):try:with open('/sd/www/index.html') as f:return f.read()except Exception as e:return f"<h1>無法加載主頁</h1><p>{e}</p>", 500# 列出 SD 根目錄所有文件,可點擊下載
# @app.route('/files')
# def list_sd_files(req):
#     try:
#         files = os.listdir('/sd')
#         html = "<!DOCTYPE html><html><head><meta charset='utf-8'><title>SD 文件列表</title></head><body>"
#         html += "<h1>📁 SD 卡文件列表</h1><ul>"
#         for name in files:
#             full_path = '/sd/' + name
#             if is_file(full_path):
#                 html += f'<li><a href="/download/{name}">{name}</a></li>'
#         html += "</ul></body></html>"
#         return html
#     except Exception as e:
#         return f"<h1>無法讀取 SD 卡文件</h1><p>{e}</p>", 500
# 文件列表頁,帶上傳表單
@app.route('/files')
def list_sd_files(req):msg = req.args.get('msg', '')try:files = os.listdir('/sd')html = """<!DOCTYPE html><html><head><meta charset='utf-8'><title>SD 文件列表</title></head><body>"""html += "<h1>📁 SD 卡文件列表</h1>"if msg:html += f"<p style='color: green;'>{msg}</p>"html += """<form method="POST" action="/upload" enctype="multipart/form-data"><input type="file" name="file"><button type="submit">上傳文件</button></form><hr><ul>"""for name in files:full_path = '/sd/' + nameif is_file(full_path):html += f"""<li><a href="/download/{name}">{name}</a><form style="display:inline" method="POST" action="/delete"><input type="hidden" name="filename" value="{name}"><button type="submit" onclick="return confirm('確定刪除文件 {name} 嗎?');">刪除</button></form></li>"""html += "</ul></body></html>"return htmlexcept Exception as e:return f"<h1>無法讀取 SD 卡文件</h1><p>{e}</p>", 500# 文件刪除接口(保持不變)
@app.route('/delete', methods=['POST'])
def delete_file(req):filename = req.form.get('filename')if not filename:return "未指定文件名", 400filepath = '/sd/' + filenameif not is_file(filepath):return "文件不存在", 404try:os.remove(filepath)return redirect(f"/files?msg=文件 {filename} 刪除成功!")except Exception as e:return f"刪除文件失敗: {e}", 500# 上傳文件接口
@app.route('/upload', methods=['POST'])
def upload_file(req):try:content_type = req.headers.get('Content-Type', '')if 'multipart/form-data' not in content_type:return "請求類型錯誤", 400boundary = content_type.split("boundary=")[-1]body = req.body# 分割上傳內容parts = body.split(b'--' + boundary.encode())for part in parts:if b'Content-Disposition' in part and b'filename=' in part:# 解析出文件名header, file_data = part.split(b'\r\n\r\n', 1)header_str = header.decode()filename = header_str.split('filename="')[-1].split('"')[0]file_data = file_data.rsplit(b'\r\n', 1)[0]  # 去除結束標記# 寫入到 SD 卡with open('/sd/' + filename, 'wb') as f:f.write(file_data)return redirect(f"/files?msg=文件 {filename} 上傳成功!")return "未找到上傳文件", 400except Exception as e:return f"上傳失敗: {e}", 500# 下載接口 —— 瀏覽器觸發下載行為 —— 保持 SD 卡原文件名
@app.route('/download/<filename>')
def download_file(req, filename):filepath = '/sd/' + filenameif not is_file(filepath):return '文件不存在', 404try:f = open(filepath, 'rb')return Response(f,headers={'Content-Type': 'application/octet-stream','Content-Disposition': 'attachment; filename="{}"'.format(filename)})except Exception as e:return f"讀取文件失敗: {e}", 500@app.route('/<path:path>')
def serve_static(req, path):full_path_www = '/sd/www/' + pathif is_file(full_path_www):try:return open(full_path_www).read()except:return '讀取失敗', 500return '404 Not Found', 404# 啟動服務器
app.run(host='0.0.0.0', port=80)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86631.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86631.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86631.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mcp-git-ingest Quickstart

目錄 配置例子 文檔github鏈接&#xff1a;git_ingest.md 配置 {"mcpServers": {"mcp-git-ingest": {"command": "uvx","args": ["--from", "githttps://github.com/adhikasp/mcp-git-ingest", "…

(LeetCode 面試經典 150 題) 27.移除元素

目錄 題目&#xff1a; 題目描述&#xff1a; 題目鏈接&#xff1a; 思路&#xff1a; 核心思路&#xff1a; 思路詳解&#xff1a; 樣例模擬&#xff1a; 代碼&#xff1a; C代碼&#xff1a; Java代碼&#xff1a; 題目&#xff1a; 題目描述&#xff1a; 題目鏈接…

MySQL之事務原理深度解析

MySQL之事務原理深度解析 一、事務基礎&#xff1a;ACID特性的本質1.1 事務的定義與核心作用1.2 ACID特性的內在聯系 二、原子性與持久性的基石&#xff1a;日志系統2.1 Undo Log&#xff1a;原子性的實現核心2.2 Redo Log&#xff1a;持久性的保障2.3 雙寫緩沖&#xff08;Dou…

JUC:5.start()與run()

這兩個方法都可以使線程進行運行&#xff0c;但是start只能用于第一次運行線程&#xff0c;后續要繼續運行該線程需要使用run()方法。如果多次運行start()方法&#xff0c;會出現報錯。 初次調用線程使用run()方法&#xff0c;無法使線程運行。 如果你對一個 Thread 實例直接調…

微服務中解決高并發問題的不同方法!

如果由于流量大而在短時間內幾乎同時發出請求&#xff0c;或者由于服務器不穩定而需要很長時間來處理請求&#xff0c;并發問題可能會導致數據完整性問題。 示例問題情況 讓我們假設有一個邏輯可以檢索產品的庫存并將庫存減少一個&#xff0c;如上所述。此時&#xff0c;兩個請…

【2025CCF中國開源大會】OpenChain標準實踐:AI時代開源軟件供應鏈安全合規分論壇重磅來襲!

點擊藍字 關注我們 CCF Opensource Development Committee 在AI時代&#xff0c;軟件供應鏈愈發復雜&#xff0c;從操作系統到開發框架&#xff0c;從數據庫到人工智能工具&#xff0c;開源無處不在。AI 與開源生態深度融合&#xff0c;在為軟件行業帶來前所未有的創新效率的同…

[Java實戰]springboot3使用JDK21虛擬線程(四十)

[Java實戰]springboot3使用JDK21虛擬線程(四十) 告別線程池爆滿、內存溢出的噩夢!JDK21 虛擬線程讓高并發連接變得觸手可及。本文將帶你深入實戰,見證虛擬線程如何以極低資源消耗輕松應對高并發壓測。 一、虛擬線程 傳統 Java 線程(平臺線程)與 OS 線程 1:1 綁定,創建和…

SpringBoot 中使用 @Async 實現異步調用?

? ? SpringBoot 中使用 Async 實現異步調用 一、Async 注解的使用場合?二、Async 注解的創建與調試?三、Async 注解的注意事項?四、總結? 在高并發、高性能要求的應用場景下&#xff0c;異步處理能夠顯著提升系統的響應速度和吞吐量。Spring Boot 提供的 Async 注解為開…

CMOS SENSOR HDR場景下MIPI 虛擬端口的使用案例

CMOS SENSOR HDR場景下MIPI 虛擬端口的使用案例 文章目錄 CMOS SENSOR HDR場景下MIPI 虛擬端口的使用案例?? **一、HDR模式下的虛擬通道核心作用**?? **二、典型應用案例****1. 車載多目HDR系統****2. 工業檢測多模態HDR****3. 手機多攝HDR合成**?? **三、實現關鍵技術點…

RJ45 以太網與 5G 的原理解析及區別

一、RJ45 以太網的原理 1. RJ45 接口與以太網的關系 RJ45 是一種標準化的網絡接口&#xff0c;主要用于連接以太網設備&#xff08;如電腦、路由器&#xff09;&#xff0c;其物理形態為 8 針模塊化接口&#xff0c;適配雙絞線&#xff08;如 CAT5、CAT6 網線&#xff09;。以…

valkey之sdscatrepr 函數優化解析

一、函數功能概述 sds sdscatrepr(sds s, const char *p, size_t len)函數的核心功能是將字符串p追加到字符串s中。在追加過程中&#xff0c;它會對字符串p中的字符進行判斷&#xff0c;使用isprint()函數識別不可打印字符&#xff0c;并對這些字符進行轉義處理&#xff0c;確…

MyBatis 緩存機制詳解

MyBatis 緩存機制詳解 MyBatis 提供了強大的緩存機制來提高數據庫訪問性能&#xff0c;主要包括一級緩存和二級緩存兩種。 一級緩存 (Local Cache) 特性&#xff1a; 默認開啟&#xff0c;作用域為 SqlSession 級別同一個 SqlSession 中執行相同的 SQL 查詢時&#xff0c;會…

設計模式精講 Day 13:責任鏈模式(Chain of Responsibility Pattern)

【設計模式精講 Day 13】責任鏈模式&#xff08;Chain of Responsibility Pattern&#xff09; 文章內容 在“設計模式精講”系列的第13天&#xff0c;我們將深入講解責任鏈模式&#xff08;Chain of Responsibility Pattern&#xff09;。這是一種行為型設計模式&#xff0c;…

h-ui面板 hysteria2

搭建文檔 項目地址&#xff1a;https://github.com/jonssonyan/h-ui/blob/main/README_ZH.md參考視頻&#xff1a;https://www.youtube.com/watch?vNi3iaLOsH_A一鍵部署命令 # root權限 sudo -ibash <(curl -fsSL https://raw.githubusercontent.com/jonssonyan/h-ui/mai…

自動登錄腳本神器-Mac電腦實現自動登錄堡壘機并自動輸入賬號密碼跳轉不同機器環境

先講下背景&#xff1a; 公司電腦需要先登錄堡壘機&#xff0c;然后再從堡壘機跳轉到具體生產機器&#xff0c;每次輸入堡壘機都要通過Authenticator里的2FC的碼做驗證&#xff0c;然后再跳到堡壘機還要再輸入一次賬號密碼&#xff0c;為了方便快速登錄機器&#xff0c;可以制…

【C/C++】C++26新特性前瞻:全面解析未來編程

展望未來&#xff1a;C26 新特性全面解析 隨著 C 標準每三年一次的迭代節奏&#xff0c;C26&#xff08;預計于 2026 年底正式發布&#xff09;正在逐步成型。相比 C20 的革命性更新和 C23 的“修補增強”&#xff0c;C26 繼續推進現代 C 的理念——更安全、更高效、更模塊化&…

ArXiv 2101 | Rethinking Interactive Image Segmentation Feature Space Annotation

Rethinking Interactive Image Segmentation Feature Space Annotation Author: lartpangLink: https://github.com/lartpang/blog/issues/10論文&#xff1a;https://arxiv.org/abs/2101.04378代碼&#xff1a;https://github.com/LIDS-UNICAMP/rethinking-interactive-image…

架構經驗總結

20250511-總結經驗 一、SOA 1&#xff09;過程&#xff1a;需求分析、系統設計、系統實現、構件組裝、部署運維、后開發階段。 2&#xff09;特點&#xff1a;無狀態、單一職責、明確定義接口、自包含、模塊化、粗粒度、重用性、兼容性、互操作性、松耦合、策略聲明。 3&…

debain切換 opensuse 我都安裝了什么

綠色進度條后&#xff0c;黑屏&#xff08;只有一個下劃線&#xff09;等待 使用 nomodeset 屬性解決 進入系統無法連接 wifi&#xff0c;只能使用網線連接 wifi 這個我在安裝中文字體后&#xff0c;注銷登錄&#xff0c;得到了解決&#xff0c;不確定是不是字體問題。&#x…

思科ISE/ISE-PIC安全警報:兩處高危RCE漏洞(CVSS 10.0)可致未授權獲取root權限

思科已發布更新&#xff0c;修復身份服務引擎&#xff08;Identity Services Engine&#xff0c;ISE&#xff09;及ISE被動身份連接器&#xff08;ISE-PIC&#xff09;中兩處最高危安全漏洞&#xff0c;這些漏洞可能允許未經認證的攻擊者以root用戶身份執行任意命令。 漏洞詳情…