ESP32 HTTPS POST上传LittleFS大文件至服务器不稳定如何解决
问题根因
你现在HTTPS上传不稳定的核心问题有4个:
- 手写裸HTTP请求时没有检查
write返回值:WiFiClientSecure的TLS发送缓冲区远小于明文WiFiClient,缓冲区满时write不会阻塞等待,只会返回实际写入的字节数,你直接按读取长度写,没写进去的字节直接丢失,服务器收到的body长度和你声明的Content-Length不匹配,直接触发连接断开。 - 请求末尾多写了一个空行:你在文件发送完之后加了
client.println(),相当于在JSON末尾多传了2字节(CRLF),实际发送长度比声明的长度多2字节,HTTP协议对长度校验严格,HTTPS下TLS帧封装会放大这个错误,几乎必然导致服务端拒绝请求。 - 没有适配TLS缓冲区:默认
WiFiClientSecure的收发缓冲区只有几百字节,传300KB+的文件时会产生大量TLS分片,极易触发内存碎片导致ESP32复位或者发送超时。 - 发送完直接断开连接:你没有读取服务器响应就直接
stop(),部分服务端会在未完成响应流程时主动发RST包重置连接,导致TLS会话异常终止。
稳定实现方案
不要自己手写裸socket的HTTP请求,直接用ESP32 Arduino核心自带的HTTPClient库,它已经封装了流控、重传、TLS适配逻辑,比手写实现稳定性高很多。替换后的上传代码如下:
#include <HTTPClient.h> #include <WiFiClientSecure.h> // 省略现有LittleFS下载逻辑,保留原有下载部分即可 if (LittleFS.exists("/downloadedFile.json")) { File uploadFile = LittleFS.open("/downloadedFile.json", "r"); if (uploadFile) { HTTPClient httpUpload; WiFiClientSecure secureClient; // 测试阶段跳过证书校验,正式环境替换为CA证书校验 secureClient.setInsecure(); // 调整TLS收发缓冲区为1KB,平衡内存占用和发送效率,减少分片 secureClient.setBufferSizes(1024, 1024); // 初始化HTTPS请求 httpUpload.begin(secureClient, "https://my.domain.com/path/to/my/endpoint"); httpUpload.addHeader("Content-Type", "application/json"); // 直接将文件流作为请求体发送,库自动处理分块、流控、长度校验 int respCode = httpUpload.sendRequest("POST", &uploadFile, uploadFile.size()); if (respCode == HTTP_CODE_OK) { // 上传成功,可按需读取服务端响应 String serverResp = httpUpload.getString(); Serial.println("Upload success"); } else { Serial.printf("Upload failed, error code: %d\n", respCode); } httpUpload.end(); uploadFile.close(); } }
可选优化项
- 正式部署时不要用
setInsecure(),导出服务端HTTPS证书的根CA,调用secureClient.setCACert(rootCACert)加载证书做校验,可进一步提升连接稳定性。 - 如果下载完立刻上传偶发崩溃,可以在两个步骤之间加
delay(50),给WiFi栈和LittleFS留出资源回收时间,避免内存峰值过高。 - 不需要手动设置分块大小,
HTTPClient的流发送逻辑会自动匹配TLS帧大小,不会出现丢字节问题。
内容的提问来源于stack exchange,提问作者Robin
相关产品推荐
相关产品推荐

