如何在 cpprestsdk 中提取写入 Concurrency::streams::fstream 的字节?

问题描述

我使用 CPPRESTSDK 创建了一个简单的客户端和服务器。客户端发送图像,然后在服务器上保存传入的文件,然后开始进行处理阶段。

现在我想检查发送的文件是否实际上是一个图像文件而不是其他一些随机文件。为此,我检查文件的前几个字节,这让我知道我在处理什么。
这是负责保存文件代码段:

//...
auto fileStream = std::make_shared<Concurrency::streams::ostream >();
Concurrency::streams::ostream outFile = Concurrency::streams::fstream::open_ostream(tmpFileName).get();
*fileStream = outFile;
uintmax_t bytesRead = 0;
int ret = 1;
bool isChecked = false;
while (ret > 0)
{
    ret = request.body().read(fileStream->streambuf(),this->READ_CHUNK).get();
    bytesRead += ret;
    
    if (!isChecked)
    {
        isChecked = true;
        auto streamBuffer = fileStream->streambuf();
        unsigned char byteBuffer[4];
        
        for (int i = 0; i < 4; i++)
        {
            byteBuffer[i] = (unsigned int)streamBuffer.bumpc().get();
            std::cout << byteBuffer[i] << ",";
        }
        // reset the read pointer
        //streamBuffer.seekpos(std::streampos(),std::ios::in);
        // check and see if this is indeed an image file
        std::string imgFormat = Utils::Misc::GetimageType(byteBuffer);
        if (imgFormat == "")
        {
            fileStream->close().get();
            auto msg = U("Unsupported file has been sent! Expected an image file such as a JPEG,PNG,OR BMP");
            this->ReplyMessage(request,status_codes::BadRequest,json::value::string(msg));
            return;
        }
    }    
    ucout << "--" << bytesRead << U(" bytes read so far[")
          << Utils::Misc::GetFileSize(bytesRead,Utils::Misc::FileSizeTypes::KByte)
          << U(" KB]") << std::endl;
    if (bytesRead > MAX_FILE_SIZE)
        break;
}
// Close the file.
fileStream->close().get();
// ...

这显然失败了,因为 fileStreamostream 并且它的 can_read 返回 false 因此 bumpc() 不起作用。那么我应该怎么做呢?如何访问底层字节缓冲区并查看到目前为止收到的内容

更新

使用 requeststreambuf() 也不会产生任何成功,因为文件指针似乎不可移动,因此执行类似 seekpos(std::streampos(0),std::ios::in) 的操作不会将其重置为开头的缓冲区。我在这里错过了什么?

解决方法

您需要通过将 mode 参数显式传递给 open_ostream function 来打开文件流以进行读取和写入。如果不指定此参数,则默认为 std::ios_base::out

Concurrency::streams::fstream::open_ostream(tmpFileName,std::ios_base::in | std::ios_base::out).get();

然后应该将文件流创建为可读的,并且您应该能够写入第一个块,回溯到文件的开头,读取四个字节,然后向前查找到第一个块的末尾。

另一种可能更简洁的方法是将第一个块读取到 stringstream,从它的前四个字节解析图像格式,然后(如果图像格式有效并且文件要保存)创建文件流,将字符串流的内容写入文件流,然后继续将剩余的文件块直接写入文件流。