如何使用C++结合SimpleAmqpClient向RabbitMQ队列写入JPEG图片?
发送JPEG图片到RabbitMQ(基于SimpleAmqpClient)
没问题,要发送JPEG这类二进制文件其实非常直接——RabbitMQ本身支持二进制消息传输,你只需要把图片的原始二进制数据正确读取出来,再封装到SimpleAmqpClient的BasicMessage里就行,完全可以复用你现有的SimplePublisher结构。
步骤1:读取JPEG文件的二进制内容
首先需要写一个工具函数,以二进制模式读取JPEG文件的全部内容。注意不能用文本模式读取,否则会丢失二进制数据(比如\0字节或者换行符的转换):
#include <fstream> #include <stdexcept> std::string read_binary_file(const std::string& file_path) { // 以二进制模式打开文件,并定位到文件末尾获取大小 std::ifstream file(file_path, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("无法打开文件: " + file_path); } std::streamsize file_size = file.tellg(); file.seekg(0, std::ios::beg); // 回到文件开头 // 分配足够的内存存储文件内容 std::string buffer(static_cast<size_t>(file_size), '\0'); if (!file.read(&buffer[0], file_size)) { throw std::runtime_error("读取文件失败: " + file_path); } return buffer; }
步骤2:发送二进制图片消息
你可以直接复用现有的SimplePublisher的第二个Publish重载(接受BasicMessage::ptr_t的版本),只需要把读取到的二进制数据塞进消息体,还可以设置ContentType方便接收端识别这是JPEG图片:
修改你的main函数如下:
#include <stdlib.h> #include <stdio.h> #include <SimpleAmqpClient/SimpleAmqpClient.h> #include <iostream> #include <fstream> #include <stdexcept> #include "SimplePublisher.h" using namespace AmqpClient; using namespace std; std::string read_binary_file(const std::string& file_path) { std::ifstream file(file_path, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("无法打开文件: " + file_path); } std::streamsize file_size = file.tellg(); file.seekg(0, std::ios::beg); std::string buffer(static_cast<size_t>(file_size), '\0'); if (!file.read(&buffer[0], file_size)) { throw std::runtime_error("读取文件失败: " + file_path); } return buffer; } int main() { char *szBroker = getenv("AMQP_BROKER"); Channel::ptr_t channel; if (szBroker != NULL) channel = Channel::Create(szBroker); else channel = Channel::Create("192.168.66.1", 5672); try { // 读取本地JPEG文件 std::string jpeg_data = read_binary_file("your_image.jpg"); // 创建消息并设置二进制内容 BasicMessage::ptr_t img_msg = BasicMessage::Create(); img_msg->Body(jpeg_data); // 设置Content-Type,让接收端知道这是JPEG图片 img_msg->ContentType("image/jpeg"); // 发送消息 boost::shared_ptr<SimplePublisher> pub = SimplePublisher::Create(channel, "wt"); pub->Publish(img_msg); cout << "JPEG图片发送成功!" << endl; } catch (const std::exception& e) { cerr << "出错了: " << e.what() << endl; return 1; } return 0; }
可选:给SimplePublisher添加专用的文件发送方法
如果需要频繁发送文件,可以给SimplePublisher添加一个专门的成员函数,让代码更整洁:
在SimplePublisher.h里声明:
void PublishFromFile(const std::string& file_path);
在SimplePublisher.cpp里实现:
void SimplePublisher::PublishFromFile(const std::string& file_path) { std::ifstream file(file_path, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("无法打开文件: " + file_path); } std::streamsize file_size = file.tellg(); file.seekg(0, std::ios::beg); std::string buffer(static_cast<size_t>(file_size), '\0'); if (!file.read(&buffer[0], file_size)) { throw std::runtime_error("读取文件失败: " + file_path); } BasicMessage::ptr_t outgoing_msg = BasicMessage::Create(); outgoing_msg->Body(buffer); outgoing_msg->ContentType("image/jpeg"); Publish(outgoing_msg); }
之后在main里直接调用:
pub->PublishFromFile("your_image.jpg");
接收端注意事项
接收图片时,一定要把消息体的二进制数据写入文件(同样用二进制模式),不要当作字符串输出(否则会因为二进制中的特殊字符导致数据丢失或乱码)。示例代码大概是:
void receive_jpeg() { Channel::ptr_t channel = Channel::Create("192.168.66.1", 5672); std::string queue_name = channel->DeclareQueue("wt"); channel->BasicConsume(queue_name, "image_consumer", false); Envelope::ptr_t envelope; if (channel->BasicConsumeMessage(envelope, 1000)) { BasicMessage::ptr_t msg = envelope->Message(); const std::string& img_data = msg->Body(); // 写入文件 std::ofstream out_file("received_image.jpg", std::ios::binary); if (out_file.is_open()) { out_file.write(img_data.data(), img_data.size()); out_file.close(); cout << "图片已保存为received_image.jpg" << endl; } else { cerr << "无法打开输出文件" << endl; } channel->BasicAck(envelope); // 确认消息已处理 } }
内容的提问来源于stack exchange,提问作者arcoxia tom




