c++通过HTTP发送图像

C++ Sending Image via HTTP

本文关键字:图像 HTTP 通过 c++      更新时间:2023-10-16

我尝试用c++实现一个简单的HTTP服务器。我可以向浏览器发送文本响应,但是我无法为二进制文件请求发送响应。

下面是我的代码,以获得HTML响应的PNG文件请求:

string create_html_output_for_binary(const string &full_path)
{
    const char* file_name = full_path.c_str();
    FILE* file_stream = fopen(file_name, "rb");
    string file_str;
    size_t file_size;
    if(file_stream != nullptr)
    {
        fseek(file_stream, 0, SEEK_END);
        long file_length = ftell(file_stream);
        rewind(file_stream);
        // Allocate memory. Info: http://www.cplusplus.com/reference/cstdio/fread/?kw=fread
        char* buffer = (char*) malloc(sizeof(char) * file_length);
        if(buffer != nullptr)
        {
            file_size = fread(buffer, 1, file_length, file_stream);
            stringstream out;
            for(int i = 0; i < file_size; i++)
            {
                out << buffer[i];
            }
            string copy = out.str();
            file_str = copy;
        }
        else
        {
            printf("buffer is null!");
        }
    }
    else
    {
        printf("file_stream is null! file name -> %sn", file_name);
    }
    string html = "HTTP/1.1 200 OkayrnContent-Type: text/html; charset=ISO-8859-4 rnrn" + string("FILE NOT FOUND!!");
    if(file_str.length() > 0)
    {
        // HTTP/1.0 200 OK
        // Server: cchttpd/0.1.0
        // Content-Type: image/gif
        // Content-Transfer-Encoding: binary
        // Content-Length: 41758
        string file_size_str = to_string(file_str.length());
        html = "HTTP/1.1 200 OkayrnContent-Type: image/png; Content-Transfer-Encoding: binary; Content-Length: " + file_size_str + ";charset=ISO-8859-4 rnrn" + file_str;
        printf("nnHTML -> %snnfile_str -> %ldnnn", html.c_str(), file_str.length());
    }
    return html;
}

这段代码成功地在char* buffer上读取文件并存储数据。让我困惑的是file_str总是包含211PNG,尽管当我检查它的大小时,它比211PNG大得多。我怀疑这是问题,导致我的图像不加载在浏览器中,因为当我打印的html,它只显示:

HTTP/1.1 200 Okay
Content-Type: image/png; Content-Transfer-Encoding: binary; Content-Length: 187542;charset=ISO-8859-4 
211PNG

我想的是发送二进制数据到浏览器的方式与发送文本数据相同,所以我先制作字符串头,然后读取文件数据,将其转换为字符串并与头结合,然后最后发送一个大的单个字符串到HTTP套接字。

我也试过这个代码:

if (file_stream != NULL)
{
    short stringlength = 6;
    string mystring;
    mystring.reserve(stringlength);
    fseek(file_stream , 0, SEEK_SET);
    fread(&mystring[0], sizeof(char), (size_t)stringlength, file_stream);
    printf("TEST -> %s, length -> %ldn", mystring.c_str(), mystring.length());
    fclose(file_stream );
}

但是HTML输出总是相同的,并且mystring在打印时也只包含211PNG

我走错路了吗?请帮忙找出我代码中的错误。谢谢你。

您将数据存储在一个std::stringstream中的大块中。这将不起作用,因为值0将被解释为空终止符。这将导致忽略空终止符之后的所有内容。你应该使用像std::vector这样的容器来存储和管理二进制数据。

#include <vector>
string create_html_output_for_binary(const string &full_path)
{
    std::vector<char> buffer;
    //... other code here
    if(ile_stream != nullptr)
    {
        fseek(file_stream, 0, SEEK_END);
        long file_length = ftell(file_stream);
        rewind(file_stream);
        buffer.resize(file_length);
        file_size = fread(&buffer[0], 1, file_length, file_stream);
    }
    // .... other code here
}

要输出数据做而不是使用printf。它可能以不同的方式处理新行,并在遇到第一个空终止符时停止。相反(与C流IO的使用保持一致)使用fwrite

fwrite (buffer.data(), 1 , buffer.size() , stdout );

为了使上面的工作,您需要重新打开stdout,使其以二进制模式写入。这个答案在Stackoverflow上展示了如何做到这一点。这只是为了将内容输出到stdout,因为您通过套接字传输日期,因此不必对stdout做任何操作。

首先,您需要打开文件(您的图片所在的位置)来读取二进制文件。

fp=fopen(filename,"rb");

接下来,使用以下命令将stdout设置为二进制模式:

 _setmode(_fileno(stdout),O_BINARY);

您需要包含<fcntl.h> and <io.h>标头。找出这幅画的确切尺寸你需要发送,例如像Captain Obvilous写的:

  fseek(fp, 0L, SEEK_END);
long file_length = ftell(fp);
rewind(fp);

现在使用fread函数从图片中读取所有字节:

    while (!feof(fp))
  {
      fread(&ch, 1, 1, fp);
      cout << ch;
  }

变量ch是char类型。当你完成设置文件模式:

_setmode(_fileno(stdout), _O_TEXT);

**注意:**这段代码主要是用C编写的,但你可以使用istream

轻松地读取c++文件