You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用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

火山引擎 最新活动