Android Java应用向ESP32 Web服务器上传.bin文件失败问题求助
解决Android上传.bin文件到ESP32 Web服务器的问题
我来帮你排查这个上传难题——既然浏览器能成功上传,说明ESP32服务器端逻辑没问题,问题肯定出在Android端的请求构造上,咱们一步步拆解修复:
一、先揪出核心错误点
你目前遇到的Connection reset和服务器500错误,主要是这几个问题导致的:
- ContentType用错了:你给二进制文件用了
text/plain,这会让OkHttp把二进制内容当成纯文本编码,ESP32解析时直接出错,返回500甚至断开连接。二进制文件必须用application/octet-stream类型。 - 表单字段名错误:你的OkHttp代码里把文件名
test-1.fw当成了表单字段名,而ESP32服务器应该是期望接收名为file的字段(和你最初HttpClient代码里的一致),服务器找不到对应字段自然报错。 - 主线程网络请求(隐性问题):如果你的代码是在主线程执行的,Android 9+会直接抛出异常,导致崩溃或无响应。
- 请求路径可能有误:你写的
/upload/file.bin和浏览器测试的/upload/不一致,要和浏览器上传的路径保持完全一致。
二、修正后的OkHttp代码示例
我把所有问题都修复了,你可以直接用这个版本测试:
// 全局初始化OkHttpClient,建议放在Application类里 private OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) // 给ESP32足够的处理时间 .writeTimeout(60, TimeUnit.SECONDS) // 大文件上传需要更长写入超时 .readTimeout(30, TimeUnit.SECONDS) .build(); public void uploadBinFile() { File file = new File("/storage/emulated/0/Download/test-1.fw"); if (!file.exists()) { Log.d("UploadDebug", "目标文件不存在"); return; } // 二进制文件正确的MediaType final MediaType binaryType = MediaType.parse("application/octet-stream"); // 注意第一个参数是服务器期望的表单字段名(必须和ESP32接收逻辑一致,这里用你最初的"file") RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", file.getName(), RequestBody.create(file, binaryType)) .build(); Request request = new Request.Builder() .url("http://10.10.2.0/upload/") // 和浏览器测试的路径保持一致 .post(requestBody) .build(); // 用异步请求,避免阻塞主线程触发异常 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e("UploadError", "上传失败", e); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { Log.d("UploadSuccess", "上传成功:" + response.body().string()); } else { Log.e("UploadError", "服务器返回错误:" + response.code() + ",详情:" + response.body().string()); } } }); }
三、额外排查步骤
如果还是有问题,试试这几个方向:
- 确认ESP32的表单字段名:打开浏览器开发者工具(F12),上传时看Network面板的Form Data,里面文件对应的字段名是什么,必须和代码里的
addFormDataPart第一个参数完全一致。 - 测试小文件:先传一个几KB的.bin文件,排除ESP32内存不足导致的连接重置。
- 检查存储权限:Android 10+的
MANAGE_EXTERNAL_STORAGE需要用户手动到设置里授权,你可以加一段权限检查代码:
if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); }
- 查看ESP32串口日志:服务器返回500时,ESP32的串口肯定会输出错误详情(比如表单解析失败、文件大小超限),这是定位问题最快的方式。
内容的提问来源于stack exchange,提问作者Brendon
相关产品推荐
相关产品推荐

