Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux CGI Web API - how to stdout a binary JPEG image under C++?

I'm writing a Web API, using CGI under linux. All is great, using gcc. I am returning an image (jpeg) to the host: std::cout << "Content-Type: image/jpeg\n\n" and now must send the binary jpeg image. Loading the image into a char* buffer and std::cout << buffer; does not work. I do get back an empty image. I suspect stdout stops on the first 00 byte.

I'm receiving from the web server a 200 OK with an incomplete image.

I was going to redirect to the file in an open folder on the device, but this must be a secure transfer and not available to anyone who knows the url.

I'm stumped!

The code snippet looks like this:

std:string imagePath;

syslog(LOG_DEBUG, "Processing GetImage, Image: '%s'", imagePath.c_str());
std::cout << "Content-Type: image/jpeg\n\n";
int length;
char * buffer;

ifstream is;
is.open(imagePath.c_str(), ios::in | ios::binary);
if (is.is_open())
{
    // get length of file:
    is.seekg(0, ios::end);
    length = (int)is.tellg();
    is.seekg(0, ios::beg);

    // allocate memory:
    buffer = new char[length];  // gobble up all the precious memory, I'll optimize it into a smaller buffer later  
                                // OH and VECTOR Victor!    
    syslog(LOG_DEBUG, "Reading a file: %s, of length %d", imagePath.c_str(), length);    
    // read data as a block:
    is.read(buffer, length);
    if (is)
    {
        syslog(LOG_DEBUG, "All data read successfully");
    }
    else
    {
        syslog(LOG_DEBUG, "Error reading jpg image");
        return false;
    }
    is.close();

    // Issue is this next line commented out - it doesn't output the full buffer
    // std::cout << buffer;

    // Potential solution by  Captain Obvlious - I'll test in the morning
    std::cout.write(buffer, length);
}
else
{
    syslog(LOG_DEBUG, "Error opening file: %s", imagePath.c_str());
    return false;
}
return true;
like image 209
Vinnie Avatar asked Nov 27 '25 11:11

Vinnie


1 Answers

As it's already been pointed out to you, you need to use write() instead of IO formatting operations.

But you don't even need to do that. You don't need to manually copy one file to another, one buffer at a time, when iostreams will be happy to do it for you.

std::ifstream is;
is.open(imagePath.c_str(), std::ios::in | std::ios::binary);
if (is.is_open())
{
    std::cout << is.rdbuf();
}

That's pretty much it.

like image 88
Sam Varshavchik Avatar answered Nov 30 '25 02:11

Sam Varshavchik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!