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

如何从React Native应用向ESP32设备POST发送二进制固件?

解决React Native向ESP32发送OTA固件时上传回调未触发的问题

核心原因分析

ESP32官方WebUpdate示例对multipart/form-data的请求格式有严格要求,React Native的FormData封装或请求配置如果和Unity的请求格式不一致,会导致ESP32无法识别上传的文件——虽然返回200 OK,但不会触发文件处理回调。

具体解决方案

1. 匹配ESP32预期的表单字段名

ESP32 WebUpdate示例默认期望文件字段名为update,必须严格对应:

const formData = new FormData();
// 第三个参数为文件名,建议和固件文件保持一致
formData.append('update', blob, 'firmware.bin');

2. 确保文件二进制数据正确读取

React Native从assets复制到文档目录后,建议通过fetch将本地文件转为Blob再封装,避免直接传文件路径可能导致的格式问题:

import RNFS from 'react-native-fs';

// 假设固件已复制到文档目录,路径为filePath
const fileUri = `file://${RNFS.DocumentDirectoryPath}/firmware.bin`;
const response = await fetch(fileUri);
const blob = await response.blob();

const formData = new FormData();
formData.append('update', blob, 'firmware.bin');

3. 修正Axios请求配置

  • 不要手动设置Content-Type为multipart/form-data:Axios会自动根据FormData生成带正确boundary的请求头,手动设置会丢失boundary,导致ESP32无法解析表单。
  • 增大超时时间:1.7MB固件上传需要一定时间,避免超时中断。
import axios from 'axios';

const config = {
  timeout: 30000, // 设置30秒超时
  maxContentLength: Infinity,
  maxBodyLength: Infinity,
  // 禁止添加 Content-Type 配置
};

try {
  const response = await axios.post('http://<ESP32_IP>/update', formData, config);
  console.log('上传响应:', response.data);
} catch (error) {
  console.error('上传失败:', error);
}

4. 分片与缓冲的必要性

1.73MB的固件不需要手动分片,ESP32的Update库默认支持的固件大小上限通常能覆盖这个尺寸(原Unity能正常上传说明你的硬件支持)。除非后续遇到更大固件,否则无需额外处理分片或转换为缓冲数组。

调试技巧

  • 抓包对比请求格式:用Charles等工具抓取Unity和React Native的请求,对比两者的请求头(尤其是boundary)、表单字段的Content-Disposition是否一致。
  • ESP32端加日志调试:在WebServer的/update接口中添加日志,确认是否识别到文件字段:
#include <WebServer.h>
#include <Update.h>

WebServer server(80);

void setup() {
  Serial.begin(115200);
  // 其他初始化逻辑...
  server.on("/update", HTTP_POST, [](){
    Serial.println("收到/update请求");
    // 打印所有表单参数名
    for (int i=0; i<server.args(); i++) {
      Serial.printf("参数%d: %s\n", i, server.argName(i).c_str());
    }
    server.sendHeader("Connection", "close");
    server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
    ESP.restart();
  }, [](){
    Serial.println("触发上传处理回调");
    HTTPUpload& upload = server.upload();
    if(upload.status == UPLOAD_FILE_START){
      Serial.printf("开始上传: %s\n", upload.filename.c_str());
      // 原Update库初始化逻辑...
    } else if(upload.status == UPLOAD_FILE_WRITE){
      // 原写入Flash逻辑...
    } else if(upload.status == UPLOAD_FILE_END){
      // 原完成处理逻辑...
    }
  });
  server.begin();
}

void loop() {
  server.handleClient();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:03:14