当前位置: 首页 > ds >正文

http协议同时传输文本和数据的新理解

首先,承认本人对于http协议认知确实不够,从来没有仔细研究这一块。

其次,这回确实要把自己十几年的理解更新一下了,主要还是自己过去没有认真研究过http协议。

这一次是这么回事,碰到一个情况,要在一次消息中传输文本和照片,这个按说很常见,过去写网页都是表单中就直接用了,也没有碰到过自己封装协议的情况。

这回呢,因为客户端是单片机,单片机这块之前也是单独提交要么文本,要么图片,没有一次性传过多种数据。

然后呢,我让kimi给我代码,结果给我的是流指针的方式

kimi错误方案一:

// 获取底层 WiFiClient 对象WiFiClient *stream = http.getStreamPtr();if (stream) {// 发送文本部分stream->print(body);// 发送图片数据stream->write(current_fb->buf, current_fb->len);// 发送结束边界stream->print(endBoundary);

WiFiClient 流指针在esp32单片机实测,压根没法正确初始化,至于原因,就不想找了,怎么测都是不行的,初始化后都是false。既然库中有这个功能,按说是能用的,也可能是我单片机中性芯片的问题。

下来事情呢,我就想自己拼接字符串给服务器。

kimi又给我错误方案二:

// 构建请求体String body;body += "--" + boundary + "\r\n";body += "Content-Disposition: form-data; name=\"message\"\r\n\r\n";body += photo_text + "\r\n";body += "--" + boundary + "\r\n";body += "Content-Disposition: form-data; name=\"image\"; filename=\"photo.jpg\"\r\n";body += "Content-Type: image/jpeg\r\n\r\n";String endBoundary = "\r\n--" + boundary + "--\r\n";// 计算总请求体长度size_t totalLen = body.length() + current_fb->len + endBoundary.length();// 设置请求体长度http.addHeader("Content-Length", String(totalLen));// 构建完整的请求体String fullBody = body;fullBody += String((char*)current_fb->buf, current_fb->len); // 直接将图片的二进制数据追加到字符串中

因为  fullBody += String((char*)current_fb->buf, current_fb->len); 其实实际加入协议的是字符串化的二进制,php服务器端 $_FILES['image'];读取的是二进制,所以肯定对不上,就会报错误3.

这个事情说明,不要完全依赖于AI,他会反复给一个错误的方向,你怎么都调不通,最终没有办法,只好自己亲自下场把内容研究透彻。

经过我和kimi的唇枪舌战,kimi终于开窍了,给我了第三个方案。【这里我要骂AI了】

// 发送HTTP POST请求Serial.println("Sending HTTP POST request");HTTPClient http;http.begin(serverURL);String boundary = "----ESP32_CAMERA_BOUNDARY";http.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);http.addHeader("User-Agent", "ESP32-Camera");http.setTimeout(60000);// 构建请求体的文本部分String body;body += "--" + boundary + "\r\n";body += "Content-Disposition: form-data; name=\"message\"\r\n\r\n";body += photo_text + "\r\n";body += "--" + boundary + "\r\n";body += "Content-Disposition: form-data; name=\"image\"; filename=\"photo.jpg\"\r\n";body += "Content-Type: image/jpeg\r\n\r\n";String endBoundary = "\r\n--" + boundary + "--\r\n";// 计算总请求体长度size_t totalLen = body.length() + current_fb->len + endBoundary.length();// 设置请求体长度http.addHeader("Content-Length", String(totalLen));// 构建完整的请求体http.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);// 发送请求http.begin(serverURL);int httpCode = http.sendRequest("POST", body.c_str(), body.length());if (httpCode == 200) {// 文本部分发送成功,现在发送图片数据http.write(current_fb->buf, current_fb->len);http.write(endBoundary.c_str(), endBoundary.length());Serial.println("Image uploaded successfully");} else {Serial.println("Failed to send text part of the request");}http.end();Serial.println("arduino HTTP request completed");

这是一个通过两次发送数据,达到目的的一个方案,这个我是可以接受的,毕竟在同一个函数任务中,但是这么一个方案明明很简单为啥AI给我搞了两天,我和他激辩很久,才告诉我。。。好吧,果然人还是要靠自己。

其实吧,这个事情还有很多解决方案,比如base64,这是经常用的,再比如使用ArduinoHttpClient库,只是这次就想死磕多类型数据协议封装,才搞了好几天。

=============================

说一下最终决定写本文的目的吧。之所以被AI的这几套方案套了三天了,根源在于自己对于http的理解有问题。也是因为没有完全了解它。

现在更正一下我的认知,我一直以为http就是一去一回的,就是送过去,返回结果。

因为用惯了api什么的,写惯了网页,之前都是这么用的,最惭愧的是以前给小弟也是这么讲的(此处脸部温度180度)。尽管我很早,在20年前就知道长连接这个事情,但是默认的访问我一直认知上认为是一去一回,然后通讯中断。

直到今天(再次脸红),我和AI沟通了原因,http1.0的协议确实默认不支持长连接,都是一去一回就完事了。本人最早用http差不多在2003年,而http1.1是1997年就出来了,所以最早的对浏览器的认知确实是有问题的,十几年来一直认为默认就是一去一回,而现在的协议肯定都是http1.1的,问了ai默认都是http1.1,也就是早就支持默认长连接,断开的话需要代码控制断开。

这次去底层拼接,才搞明白这个事,真的是愚钝了。(脸红+1)

http://www.xdnf.cn/news/13388.html

相关文章:

  • 可编辑前端列表页面,让你的用户直接粘贴录入数据
  • pdf.js在iOS移动端分页加载优化方案(ios移动端反复刷新加载问题)
  • dedecms 织梦自定义表单留言增加ajax验证码功能
  • 传统影像的盲区:心血管疾病诊断的新突破与未来
  • H5流媒体播放器EasyPlayer.js对H.265编码MP4文件的播放支持应用方案
  • C++_核心编程_多态案例二-制作饮品
  • 【JVM】- 垃圾回收
  • 字符串方法_indexOf() +_trim()+_split()
  • 6.10 - 常用 SQL 语句以及知识点
  • 【threejs】每天一个小案例讲解:常见几何体
  • Android --- Handler的用法,子线程中怎么切线程进行更新UI
  • 清华大学视觉空间智能新突破!Spatial-MLLM:提升多模态大语言模型的视觉空间智能能力
  • 3通道图的数据在opencv的mat是如何存放的
  • flow_controllers
  • plantuml画uml图
  • Python实例题:Python计算离散数学
  • 使用swagger来生成文档
  • C++中优雅的属性封装:Sint类设计分析
  • 网络六边形受到攻击
  • PLC入门【5】基本指令3(PLS PLF ZRST)
  • TestCafe API
  • vue3 + element plus -- table表格使用sortablejs实现表格拖拽换位功能
  • 麒麟Kylin V10 SP3服务器操作系统安装
  • 项目进度管理软件是什么?项目进度管理软件有哪些核心功能?
  • LoRA(Low-Rank Adaptation,低秩适应)
  • leetCode- 两数相加
  • 【AI学习】一、向量表征(Vector Representation)
  • 报告精读:金融算力基础设施发展报告 2024【附全文阅读】
  • 构建欺诈事件的结构化威胁建模框架
  • Coze 和 Dify 对比