You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:在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提示页面

使用说明

  1. 在Pico W的/webroot/目录下放入你的data.csv文件(与leaf.jpg同目录)
  2. 修改代码中的ssid和password为你的WiFi账号密码
  3. 上传代码到Pico W并运行,访问打印出的IP地址,点击页面链接即可下载正确的CSV文件

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 17:38:12