在这里插入图片描述

  • 以下是整合了所有功能的完整 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用户身份执行任意命令。 漏洞详情…