这篇教程将带领大家去了解如何使用 ESP32-CAM 板和 Arduino IDE 发出 HTTP POST 请求,以将照片发送到服务器。我们将展示如何将 JPG/JPEG 图像发布到本地服务器(Raspberry Pi LAMP 服务器)或云服务器(您可以从任何地方访问)。照片将显示在图库中,您可以在其中查看或删除照片。要将图像保存在服务器中并创建图库,我们将使用 PHP 脚本。
要构建此项目,您需要执行以下步骤。按照LAMP Server或Hosting Server的说明进行操作,这取决于您要在本地还是从任何地方访问照片。
- 托管您的PHP应用程序
- Raspberry Pi LAMP服务器(本地访问)
- 托管服务器(可从任何地方访问)
- PHP脚本可在服务器中保存和显示照片
- Raspberry Pi LAMP服务器(本地访问)
- 托管服务器,比如阿里云腾讯云之类的都可以,可以申请免费试用(可从任何地方访问)
- 使用Arduino IDE对ESP32-CAM进行编程
- 测试和最终演示
目录
1.托管您的PHP程序
该项目的目标是拥有一个本地或云服务器来存储和访问您的ESP32-CAM照片。
1. Raspberry Pi本地服务器:
使用Raspberry Pi LAMP服务器,您可以在本地访问图像(如下图所示),这个环节需要有在树莓派搭建LAMP服务器的基础,这部分本篇教程不详细讲,可以参考这篇文章:点击查看
- 您可以在Raspberry Pi上运行LAMP(Linux,Apache,MySQL,PHP)服务器,以访问本地网络中的数据。Raspberry Pi LAMP服务器:用于在本地访问映像的本地Linux服务器。
2.云服务器(阿里云解决方案)
您还可以通过访问您自己的服务器+域,在世界任何地方可视化ESP32-CAM照片。以下是有关其工作原理的概述:
建议购买学生主机,比较便宜,然后再购买域名,可以买最便宜的,当然不买也行。这是这个项目的有趣之处:你可以访问您的域名 (http://example.com) 并查看您的 ESP32-CAM 照片。如果不知道怎么操作的,可以联系作者指导购买和部署!
HTTP POST请求方法
超文本传输协议 (HTTP) 用作客户端和服务器之间的请求-响应协议。下面是一个例子:
- ESP32(客户端)向 Server(例如:本地 RPi Lamp Server 或 example.com)提交 HTTP 请求;
- 服务器向 ESP32(客户端)返回响应;
HTTP POST用于将数据发送到服务器以创建/更新资源。例如,将图像发布到服务器。
POST /upload.php HTTP/1.1
Host: example.com
Content-Type: image/jpeg
2.1. 准备您的.php文件和上传文件夹(Raspberry Pi LAMP 服务器)
本部分为您的 Raspberry Pi LAMP 服务器准备.php文件和上传文件夹。如果您使用自己的服务器 + 域名,请跳到下一部分。
让Raspberry Pi 运行 Apache 和 PHP,在 Raspberry Pi 板终端窗口中导航到/var/www/html/目录:
pi@raspberrypi:~ $ cd /var/www/html/
创建一个名为uploads的新文件夹:
pi@raspberrypi:/var/www/html $ mkdir uploads
pi@raspberrypi:/var/www/html $ ls
uploads
目前,/var/www/html归 root 所有,使用下一个命令更改为 pi 用户并授予其所有权限,以便您稍后可以使用 PHP 脚本保存照片。
sudo chown -R pi:pi /var/www/html
chmod -R 777 /var/www/html/
最后,新建一个upload.php文件:
pi@raspberrypi:/var/www/html $ nano upload.php
这个 PHP 脚本负责从 ESP32-CAM 接收传入的图像,用时间戳重命名图像并将它们存储在上传文件夹中。编辑新创建的文件 ( upload.php ) 并复制以下代码段:
<?php
// Code Based on this example: w3schools.com/php/php_file_upload.asp
$target_dir = "uploads/";
$datum = mktime(date('H')+0, date('i'), date('s'), date('m'), date('d'), date('y'));
$target_file = $target_dir . date('Y.m.d_H:i:s_', $datum) . basename($_FILES["imageFile"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["imageFile"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
$uploadOk = 1;
}
else {
echo "File is not an image.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["imageFile"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
}
else {
if (move_uploaded_file($_FILES["imageFile"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["imageFile"]["name"]). " has been uploaded.";
}
else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
您的upload.php文件应如下所示。保存文件并退出(Ctrl+X、Y 和 Enter 键):
然后,创建一个新的gallery.php文件:
pi@raspberrypi:/var/www/html $ nano gallery.php
编辑新创建的文件 ( gallery.php ) 并复制以下代码段:
<!--
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-->
<!DOCTYPE html>
<html>
<head>
<title>ESP32-CAM Photo Gallery</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-container > div {
text-align: center;
margin: 10px;
}
</style>
</head><body>
<h2>ESP32-CAM Photo Gallery</h2>
<?php
// Image extensions
$image_extensions = array("png","jpg","jpeg","gif");
// Check delete HTTP GET request - remove images
if(isset($_GET["delete"])){
$imageFileType = strtolower(pathinfo($_GET["delete"],PATHINFO_EXTENSION));
if (file_exists($_GET["delete"]) && ($imageFileType == "jpg" || $imageFileType == "png" || $imageFileType == "jpeg") ) {
echo "File found and deleted: " . $_GET["delete"];
unlink($_GET["delete"]);
}
else {
echo 'File not found - <a href="gallery.php">refresh</a>';
}
}
// Target directory
$dir = 'uploads/';
if (is_dir($dir)){
echo '<div class="flex-container">';
$count = 1;
$files = scandir($dir);
rsort($files);
foreach ($files as $file) {
if ($file != '.' && $file != '..') {?>
<div>
<p><a href="gallery.php?delete=<?php echo $dir . $file; ?>">Delete file</a> - <?php echo $file; ?></p>
<a href="<?php echo $dir . $file; ?>">
<img src="<?php echo $dir . $file; ?>" style="width: 350px;" alt="" title=""/>
</a>
</div>
<?php
$count++;
}
}
}
if($count==1) { echo "<p>No images found</p>"; }
?>
</div>
</body>
</html>
这个 PHP 脚本负责在图库上显示图像。您的gallery.php文件应如下所示。保存文件并退出(Ctrl+X、Y 和 Enter 键):
2.2. 准备您的.php文件和上传文件夹(云服务)
如果您更喜欢远程运行服务器并从任何地方访问照片,您需要一个托管帐户,这里建议采用阿里云或腾讯云的学生主机,比较便宜,具体注册方法,这里就不详细讲解了,感兴趣的可以自己在百度上搜索下。
步骤如下:
- 注册云服务器
- 搭建php服务,新手推荐宝塔面板,简单方便
- 创建网站,没有域名的直接用ip访问也是ok的
- 上传php文件到网站根目录,php文件内容如下:
这个 PHP 脚本负责从 ESP32-CAM 接收传入的图像,用时间戳重命名图像并将它们存储在上传文件夹中。编辑新创建的文件 ( upload.php ) 并复制下面的代码段:
<?php
// Code Based on this example: w3schools.com/php/php_file_upload.asp
$target_dir = "uploads/";
$datum = mktime(date('H')+0, date('i'), date('s'), date('m'), date('d'), date('y'));
$target_file = $target_dir . date('Y.m.d_H:i:s_', $datum) . basename($_FILES["imageFile"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["imageFile"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
$uploadOk = 1;
}
else {
echo "File is not an image.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["imageFile"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
}
else {
if (move_uploaded_file($_FILES["imageFile"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["imageFile"]["name"]). " has been uploaded.";
}
else {
echo "Sorry, there was an error uploading your file.";
}
}
?>
保存您的文件并退出。
然后,编辑gallery.php文件并复制以下代码段。这负责在图库中显示图像:
<!--
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
-->
<!DOCTYPE html>
<html>
<head>
<title>ESP32-CAM Photo Gallery</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-container > div {
text-align: center;
margin: 10px;
}
</style>
</head><body>
<h2>ESP32-CAM Photo Gallery</h2>
<?php
// Image extensions
$image_extensions = array("png","jpg","jpeg","gif");
// Check delete HTTP GET request - remove images
if(isset($_GET["delete"])){
$imageFileType = strtolower(pathinfo($_GET["delete"],PATHINFO_EXTENSION));
if (file_exists($_GET["delete"]) && ($imageFileType == "jpg" || $imageFileType == "png" || $imageFileType == "jpeg") ) {
echo "File found and deleted: " . $_GET["delete"];
unlink($_GET["delete"]);
}
else {
echo 'File not found - <a href="gallery.php">refresh</a>';
}
}
// Target directory
$dir = 'uploads/';
if (is_dir($dir)){
echo '<div class="flex-container">';
$count = 1;
$files = scandir($dir);
rsort($files);
foreach ($files as $file) {
if ($file != '.' && $file != '..') {?>
<div>
<p><a href="gallery.php?delete=<?php echo $dir . $file; ?>">Delete file</a> - <?php echo $file; ?></p>
<a href="<?php echo $dir . $file; ?>">
<img src="<?php echo $dir . $file; ?>" style="width: 350px;" alt="" title=""/>
</a>
</div>
<?php
$count++;
}
}
}
if($count==1) { echo "<p>No images found</p>"; }
?>
</div>
</body>
</html>
保存您的文件并退出。就是这样!您的服务器已准备就绪。
3. ESP32-CAM HTTP 将图像/照片发布到服务器
现在您已准备好服务器(Raspberry Pi LAMP 服务器或云服务器),是时候准备带有代码的 ESP32-CAM,每 30 秒向您的服务器发布一次新图像。在继续本教程之前,请确保您完成以下先决条件。
所需零件
要遵循本教程,您需要以下组件:
- 带有 OV2640 的 ESP32-CAM
- FTDI编程器
- 母对母连接线
- ESP32-CAM 5V 电源
- 本地服务器:
- Raspberry Pi 板 (树莓派)
- MicroSD 卡 – 32GB Class10
- 树莓派电源(5V 2.5A)
- 云服务器(替代):阿里云腾讯云等云服务器
Arduino IDE环境
我们将 使用 Arduino IDE对 ESP32-CAM进行编程,因此请确保您已安装 ESP32 环境组件。
检查 PHP 网址
您应该尝试打开 Raspberry Pi 本地 IP 地址或您的外部 example.com 域名,然后是/upload.php应该返回:
Sorry, only JPG, JPEG, PNG & GIF files are allowed.Sorry, your file was not uploaded.
如果您看到该消息保存了您的 URL/域名和路径,则您的服务器应该已准备就绪,您可以继续阅读本指南。
此外,尝试访问/gallery.php路径。你应该得到如下所示的东西:
ESP32-CAM 代码
下一个程序使用HTTP POST将图像发布到服务器。将下面的代码复制到您的 Arduino IDE:
在上传代码之前,您需要在以下变量中插入您的网络凭据:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
确保选择正确的相机模块,这里我们使用 AI-THINKER 模块。
添加您的 Raspberry Pi IP 地址或使用服务器域名:
String serverName = "192.168.1.XXX"; // REPLACE WITH YOUR Raspberry Pi IP ADDRESS
//String serverName = "example.com"; // OR REPLACE WITH YOUR DOMAIN NAME
String serverPath = "/upload.php"; // The default serverPath should be upload.php
上传代码到 ESP32-CAM
现在您可以将代码上传到您的 ESP32-CAM 板。使用FTDI 编程器将 ESP32-CAM 板连接到您的计算机。
连接示意图:
许多 FTDI 编程器都有一个连接线,可以让您选择 3.3V 或 5V。确保连接线在正确的位置以选择 5V。
重要的: 通用输入输出口 0 需要连接到 GND 以便您能够上传代码。
ESP32-CAM | FTDI 程序员 |
GND | GND |
5V | VCC (5V) |
U0R | TX |
U0T | 接收 |
通用输入输出口 0 | GND |
要上传代码,请按照以下步骤操作:
- 转到工具> 开发板并选择AI-Thinker ESP32-CAM。
- 转到工具>端口并选择 ESP32 连接的 COM 端口。
- 然后,单击上传按钮上传代码。
- 当您开始在调试窗口中看到这些点时,如下图所示,按下 ESP32-CAM 板载 RST 按钮。
几秒钟后,代码应该会成功上传到您的开发板。
代码的工作原理
这是有关代码如何工作的快速解释:
- 导入所有库;
- 定义所需的变量;
- 定义相机引脚;
- 在里面 setup() 您建立 Wi-Fi 连接并初始化 ESP32 相机。
- 这 loop() 有一个定时器调用sendPhoto()每 30 秒运行一次。您可以在定时器间隔 variable。
这 sendPhoto()功能是实际拍摄照片并将其发送到您的服务器的部分。您可以在需要拍摄照片并将其发布到服务器的其它项目中使用该功能。
4. 测试和最终演示
将代码上传到您的开发板后,打开 Arduino IDE 串行监视器,您应该会看到每 30 秒打印一次类似的消息:
The file esp32-cam.jpg has been uploaded.
如果您访问本地服务器 URL http://IP-Address/uploads或云服务器 URL http://example.com/uploads,您应该有一个包含所有存储照片的文件夹。
您可以打开每个链接以打开带有完整图像的新页面:
现在,如果您转到本地服务器 URL http://IP-Address/gallery.php或云服务器 URL http://example.com/gallery.php,则可以访问图库页面,您可以在其中查看和删除照片。
要删除任何照片,只需单击每张图像旁边的“删除文件”链接。
问些问题,麻烦指导一下。主要是我这边编译那句head不通过,我后来找了另外一个描述,最后能编译,连接服务器也没问题,但是在client.available()的时候变成了………..,这啥情况呀。是跟我head修改了而无法读取么
你看看你服务器有没有开防火墙之类的
我想问一下这个数组好像不能装很大的图片,这个数组,有办法上传10m的图片么,有个方法思路什么的额指点指点。谢谢
超过10M的没测试过,理论上是可以的
在upload.php里面我找到了相关文件大小限制的句子,修改这个只会,再进行测试。刚好是限制的500KB左右【488kb】
这是我修改head后的内容,用之前的一直无法成功通过编译,图片有Q,有群可以拉我交流一下,太难了。服务器也准备好了,就这里上传好像卡住了
用这个代码:https://notes.qutaojiao.com/share.html?shareID=D/GywuMotTFjHuWmid9/Rc1jXvkj+FEvarhQ0+6Tbd0
兄弟,已收到你得代码,我更换了head,就好了,看来,这个网页确实只接收你得head字段内容。 万分感谢。已收到这段编辑代码,很好用。谢谢 。我之前确实在搜集相关资料,你得这篇文章很齐全。很好。
学习了
您好,请问按照您的步骤完成配置后,检查 PHP 网址是没问题的。
然后改了网络配置和ip地址。烧录成功后,连不上服务器。求助。
ESP32-CAM IP Address: 192.168.246.159
Connecting to server: 42.101.38.156:8090
Connection to 42.101.38.156:8090 failed.
请问是不是端口号的事情,
const int serverPort = 80; 我服务器是8090(小白求指导)
你先用接口调试工具本地试试能不能正常上传,可以的话单片机也是没问题的
博主大佬,能不能给个联系方式,万分感谢
String serverName = “42.101.38.156”; // REPLACE WITH YOUR Raspberry Pi IP ADDRESS
//String serverName = “example.com”; // OR REPLACE WITH YOUR DOMAIN NAME
String serverPath = “/upload.php”; // The default serverPath should be upload.php
const int serverPort = 8090;
我修改后,能连了,但是报错,哭了
Connecting to server: 42.101.38.156
Connection successful!
…..
Sorry, there was an error uploading your file.
服务器端的防火墙策略设置有没有问题啊?也有可能图片太大了,或者网络不稳定
有大佬复现过这个项目吗?
我搞出来了,(首先保证服务器配了阿帕奇、mysql、php,有uploads文件夹等),esp32代码有错,很多rn都缺少转义字符,head里的双引号也要加,这些修改了之后,串口监视器返回”Sorry, there was an error uploading your file.”,修改文件夹权限为777之后就成功了sudo chmod -R 777 uploads
我简单写了下,可以看下我发布的,还是要谢谢你的文章?
你好,请问您发布到了哪里,我可以去看看吗?
https://www.qutaojiao.com/108463.html
[…] […]
@Luca 大佬你好,我有几个问题: 1. 你的代码里转义符是不是写错了,应该是rn,你写的rn 2. 你在另一篇文章里写了upload.php和uploads都放在/html/下面,但是这篇文章又是放在/下面的,我想知道到底放哪了,我试了,放/下面会收到来自.php的错误提示error,而放到/html下面则会变成404(找不到)
根据你实际的接收路劲来,如果是放在我们测试接口,那就按照这个代码就可以:https://notes.qutaojiao.com/share.html?shareID=D/GywuMotTFjHuWmid9/Rc1jXvkj+FEvarhQ0+6Tbd0
感谢
怎样建立本地服务器,接收查看图片呢?
本地服务可以搭建一下php的环境
兄弟,你的资料非常详细,我也学习学习😁
复刻此教程后,修改upload.php文件可以上传大文件图片。并附上,我上传文件大小网速测试,是连接的我手机热点测试的上传速度。大家可以参考,ESP32_CAM的话,基本上很快就可以上传
顺道一提,如何进行大文件得上传。我首先得打好SD卡数据读取写入得基础,我看到程序中发给云端得那段函数,我分析了半天进行了测试,道理跟之前其它论坛SD卡写入数据函数一样,无非是判断当前文件大小进行写入1024,小于1024了,开始写入尾数文件,在常用得一道循环中,我们可以摒弃*fbbuf=buf,这赋值一步,直接进行数据READ,循环读取写入到http,当然其中,我基础不好,测试了很久,长达30多个小时吧,理解每一段用意,优化,希望对其它人有所帮助
手机买了代码咋电脑上还需要购买啊
你登陆了就不需要
登陆了应该不需要的
@Luca 大神你好 测试过程中发现 第一张照片正常 第二张上传的照片好像会延迟两帧上传 第一张setup里拍完照我就对着脸了 结果是第四次上传才出现脸的照片 脸的照片应该在第二次上传出现的 不知道问题在哪 能帮解答一下吗 非常感谢。。
这个问题我自己解决了 虽然不知道具体问题是啥 但这方法可行 有大神可以从根本上解决 从照片看头两张照片明显颜色不正常 后面都正常 所以照片前两张有问题 我们拍照拍三次 头两次不用 用第三次的 就行了 String sendPhoto() { String getAll; String getBody; camera_fb_t * fb = NULL; //加两次拍照释放 fb = esp_camera_fb_get(); esp_camera_fb_return(fb); fb = esp_camera_fb_get(); esp_camera_fb_return(fb); //第三次拍照用于上传 fb = esp_camera_fb_get();
另外我对服务器端和esp32端代码进行了修改 可以返回图片上传的网络地址 需要的话我可以发出来共享一下😁
您可以发出来共享一下嗎? spock@twinnet.com.tw
连接服务器失败是什么原因
排查:1、检查wifi连接是否正常
2、自己在浏览器上访问一下接口看看能不能正常访问,可以正常访问的话一般不会连接服务器失败;