求助:在Pico W基础Web服务器下载CSV文件时格式异常
解决Pico W Web服务器CSV下载显示为HTML的问题
问题原因
你的代码仅处理了.jpg格式的请求,所有其他请求(包括.csv)都会走默认分支返回HTML页面内容,同时响应头的Content-type设为text/html,导致浏览器把CSV内容识别成HTML文件。
修复后的完整代码
# 基于Raspberry Pi官方文档修改的Pico W Web服务器代码 import network import time from machine import Pin import uasyncio as asyncio onboard = Pin("LED", Pin.OUT, value=0) ssid = "你的WiFi名称" password = "你的WiFi密码" # 更新HTML页面,添加CSV下载链接 html = """<!DOCTYPE html> <html> <head> <title>Pico W 文件下载</title> </head> <body> <h1>My Pico W</h1> <img src="/leaf.jpg"> <!-- 修正原代码拼写错误:ims -> img --> <p>点击下方链接下载CSV文件:</p> <a href="/data.csv">下载数据.csv</a> </body> </html> """ webdocs = "/webroot/" wlan = network.WLAN(network.STA_IF) def connect_to_network(): wlan.active(True) wlan.config(pm = 0xa11140) # 禁用省电模式 wlan.connect(ssid, password) max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('等待连接...') time.sleep(1) if wlan.status() != 3: raise RuntimeError('网络连接失败') else: print('已连接') status = wlan.ifconfig() print('IP地址 = ' + status[0]) async def serve_client(reader, writer): print("客户端已连接") request_line = await reader.readline() print("请求内容:", request_line) # 跳过HTTP请求头 while await reader.readline() != b"\r\n": pass request = str(request_line) # 识别请求的文件类型 is_jpg = request.find('.jpg') > 0 is_csv = request.find('.csv') > 0 if is_jpg: # 处理图片请求 requested_file = request[6:request.find('.jpg')+4] print("请求图片文件:", requested_file) try: with open(webdocs + requested_file, 'rb') as f: response = f.read() # 设置图片响应头 writer.write(b'HTTP/1.0 200 OK\r\nContent-type: image/jpeg\r\n\r\n') writer.write(response) except OSError: # 文件不存在返回404 writer.write(b'HTTP/1.0 404 Not Found\r\nContent-type: text/html\r\n\r\n') writer.write(b'<h1>文件不存在</h1>') elif is_csv: # 处理CSV下载请求 requested_file = request[6:request.find('.csv')+4] print("请求CSV文件:", requested_file) try: with open(webdocs + requested_file, 'rb') as f: response = f.read() # 设置CSV专属响应头,触发浏览器下载动作 writer.write(b'HTTP/1.0 200 OK\r\n') writer.write(b'Content-type: text/csv\r\n') writer.write(b'Content-Disposition: attachment; filename="data.csv"\r\n\r\n') writer.write(response) except OSError: writer.write(b'HTTP/1.0 404 Not Found\r\nContent-type: text/html\r\n\r\n') writer.write(b'<h1>文件不存在</h1>') else: # 返回主页HTML writer.write(b'HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') writer.write(html.encode('utf-8')) await writer.drain() await writer.wait_closed() print("客户端已断开连接") async def main(): print('连接网络中...') connect_to_network() print('设置Web服务器...') asyncio.create_task(asyncio.start_server(serve_client, "0.0.0.0", 80)) while True: onboard.on() print("心跳") await asyncio.sleep(0.25) onboard.off() await asyncio.sleep(5) try: asyncio.run(main()) finally: asyncio.new_event_loop()
关键修改点
- 新增CSV请求处理分支:识别
.csv后缀的请求,读取对应文件并返回正确内容 - 配置正确的响应头:
Content-type: text/csv:告知浏览器文件为CSV格式Content-Disposition: attachment; filename="data.csv":强制浏览器触发下载动作,而非直接打开
- 二进制模式读取文件:用
'rb'模式打开文件,避免文本模式下的编码或换行符转换问题 - 修复原代码错误:将HTML中的
<ims>修正为<img> - 增加错误处理:文件不存在时返回404提示页面
使用说明
- 在Pico W的
/webroot/目录下放入你的data.csv文件(与leaf.jpg同目录) - 修改代码中的
ssid和password为你的WiFi账号密码 - 上传代码到Pico W并运行,访问打印出的IP地址,点击页面链接即可下载正确的CSV文件
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

