⭐简介
本文是在 ESP32-CAN 中实现的,其他单片机实现方法一致,主要涉及 HTTP 发送文件。本章所采用的请求为 POST 请求 。GET 请求会更容易 。
♾️目录
⭐分别讲解
?HTTP请求报文头
HTTP 请求报文格式如图:请求方法为 POST 或者 GET 。URL 为 请求地址,可以为 / 。协议版本 HTTP/1.1即可。 回车符 \r 换行符\n
有几个必不可少的头部字段:
Host服务器的域名/IP地址和端口号Content-Type内容类型Content-Length内容大小
?HTTP 请求报文体
我们要发送文件,所以报文体当然就是文件了,当然,文件也有专门用来发送的格式
其中一种格式为:
–【随机码】【\r\n】
Content-Disposition: form-data; name=【数据标识】; filename=“【文件名】”【\r\n】
Content-Type: 【文件类型】【\r\n】
【文件二进制编码流】
–【随机码】–
文件类型如果是JPG的话就是image/jpeg
?整合报文
Content-Type
随机码要在请求头 Content-Type 告诉服务器随机码是什么
Content-Type: multipart/form-data; boundary=【随机码】
Content-Length
Arduino 的 String 太长会出现BUG,所以我们还是用手动计算的方式来获取请求体的大小,而不是全部整合到一个字符串中再求字符串长度。
// 二进制流前面的报文
String fileHead = "--" + randomCode + "\r\n" +
"Content-Disposition: form-data; name=\"img\"; filename=\"" + randomCode + ".jpg\"" + "\r\n" +
"Content-Type: image/jpeg" + "\r\n";
// 获取文件大小
size_t jpgsize = 0 ;
for( jpgsize = 0 ; ;jpgsize++ ){
if( fb->buf[jpgsize] == 0xff ){
if( fb->buf[jpgsize+1] ==0xd9 ){
jpgsize += 2 ;
break;
}
}
}
// 太大了就转 long 或者直接转String
unsigned int bodySize = ( fileHead.length() + (jpgsize) + randomCode.length() + 4 + 2 );
Content-Length: 【bodySize请求体大小】
?按顺序发送
做完这几步以后,就可以把我们的报文按顺序发送出去了,下面有一个 ESP32-CAN 发送一张图片并获取响应的例子。
⭐ESP32-CAN实现图片上传代码段
void send_camera_img(){
// acquire a frame
WiFiClient client;
camera_fb_t *fb = esp_camera_fb_get();
// 域名 请求地址
string domain = "" ;
if ( client.connect(domain,80)){
Serial.println(" Success!"); // 连接成功后串口输出“Success”信息
} else{ // 如果连接不成功则通过串口输出“连接失败”信息
Serial.println(" connection failed!");
client.stop();
return ;
}
if (!fb)
{
Serial.print("Camera capture failed");
}
else
{
// 随机编码
String randomCode = "";
for( int i = 0 ; i < 10 ; i ++ ){
// 生成随机编码
switch ( random(0,3) ){
case 0 :
randomCode += (char)random(48,58);
break;
case 1 :
randomCode += (char)random(65,91);
break;
case 2 :
randomCode += (char)random(97,123);
break;
}
}
String fileHead = "--" + randomCode + "\r\n" +
"Content-Disposition: form-data; name=\"img\"; filename=\"" + randomCode + ".jpg\"" + "\r\n" +
"Content-Type: image/jpeg" + "\r\n";
// 获取文件大小
size_t jpgsize = 0 ;
for( jpgsize = 0 ; ;jpgsize++ ){
if( fb->buf[jpgsize] == 0xff ){
if( fb->buf[jpgsize+1] ==0xd9 ){
jpgsize += 2 ;
break;
}
}
}
// 发送文件头
client.println("POST / HTTP/1.1");
Serial.println("POST / HTTP/1.1");
client.println("Host: "+ domain);
Serial.println("Host: "+ domain);
client.println("Content-Type: multipart/form-data; boundary=" + randomCode );
Serial.println("Content-Type: multipart/form-data; boundary=" + randomCode );
client.println("Connection: close");
Serial.println("Connection: close");
client.println("Content-Length: " + String( fileHead.length() + (jpgsize) + randomCode.length() + 4 + 2 ) );
Serial.println("Content-Length: " + String( fileHead.length() + (jpgsize) + randomCode.length() + 4 + 2 ) );
client.println("");
Serial.println("");
// 发送文件
client.println( fileHead );
Serial.println( fileHead );
for (size_t i = 0; i < jpgsize; i++)
{
client.write(fb->buf[i]); // payload , lengte vd payload
}
// return the frame buffer back to the driver for reuse
client.println("");
client.print("--" + randomCode + "--");
Serial.println("--" + randomCode + "--");
// 清除摄像头缓存
esp_camera_fb_return(fb);
// 获取 API 返回报文
rubbishMeg = "";
while (client.connected() || client.available()){
if (client.available()){
char line = client.read();
rubbishMeg += line ;
Serial.print(line);
}
}
}
client.stop();
}
⭐联系作者
✍️本文作者为 > 【谢玄.】 Mr-XieXuan < 于 2022/10/13/03:00:00 发布于 CSDN 。
⌨️GitHub: [ https://github.com/MR-XieXuan }
?个人私站: [ https://main.mrxie.xyz/ ]
版权声明:本文为apple_53792700原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。