C++ C++;windows中二进制文件的gsoap mime/dime

C++ C++;windows中二进制文件的gsoap mime/dime,c++,binary,mime,gsoap,C++,Binary,Mime,Gsoap,在这里我几乎要失去理智了;) 我正在开发一个使用gsoap的服务。我想返回一个mime回复。 我有一切工作,但当阅读二进制文件,所有类型的文件,如jpeg,pdf等。。。在数据上多次包含\0字符(如果用记事本打开,可以看到大量NUL) 因此,任何读取原始文件的代码一旦找到文件末尾字符,都会失败。我试图替换\0,但文件显示不正确 我还尝试了几种方法,包括gsoap附带的示例 那么恢复, fstream通用代码不起作用 for (i = 0; i < MAX_FILE_SIZE; i++)

在这里我几乎要失去理智了;)

我正在开发一个使用gsoap的服务。我想返回一个mime回复。 我有一切工作,但当阅读二进制文件,所有类型的文件,如jpeg,pdf等。。。在数据上多次包含
\0
字符(如果用记事本打开,可以看到大量
NUL

因此,任何读取原始文件的代码一旦找到文件末尾字符,都会失败。我试图替换
\0
,但文件显示不正确

我还尝试了几种方法,包括gsoap附带的示例

那么恢复,

fstream通用代码不起作用

for (i = 0; i < MAX_FILE_SIZE; i++)
    { if ((c = fgetc(fd)) == EOF)
        break;
      image.__ptr[i] = c;
    } 
但是没有运气。。。mime响应比实际文件大

David G Ortega要读取二进制文件,请使用 一旦读取它,就将其视为字节数组,而不是字符串。不允许使用字符串函数

编辑:第14.1节解释了如何发送MIME附件。我只参考相关功能(请通读)

char*buf_ptr
是您的缓冲区。
size\t buf\u size
是缓冲区的长度

所以只需执行
QFile::ReadAll

这将返回一个
QByteArray
。QByteArray具有以下方法

QByteArray QByteArray::toBase64()常数

这将返回一个

 QByteArray base64image = QByteArray::toBase64(rawImage);    
所以现在就做吧

soap_set_mime(soap, "MIME_boundary", "<boundary.xml@just-testing.com>"); 
/* add a base64 encoded image (base64image points to base64 data) */ 
soap_set_mime_attachment(soap, 
        base64image.data(), base64image.size(), 
        SOAP_MIME_BASE64, "image/jpeg", 
        "<boundary.jpeg@just-testing.com>", NULL, NULL); 
soap\u set\u mime(soap,“mime\u边界”);
/*添加base64编码图像(base64图像指向base64数据)*/
soap\u set\u mime\u附件(soap,
base64image.data(),base64image.size(),
SOAP_MIME_BASE64,“图像/jpeg”,
“”,空,空);
我还没有测试这个,但应该接近完成

QFile::ReadAll可以工作,但是当将QString转换为char*时,数组在第一个NUL中被修剪

是否确实已修剪该数组,或者无法在调试器中打印/查看该数组[因为C样式字符串以0结尾]

如果QString本身不足以满足您的需要,您可能希望使用range构造函数或range assign将其转换为std::vector或类似的格式,那么您对容器所保存的数据量的担忧就会大大减少

编辑: 以下是从二进制文件读取fstream的一些示例代码:

std::ifstream image( <image_file_name>, std::ios_base::in | std::ios_base::binary );
std::istream_iterator< char > image_begin( image ), image_end;
std::vector< char > vctImage( image_begin, image_end ); 
std::ifstream映像(,std::ios_base::in | std::ios_base::binary);
std::istream\u迭代器image\u开始(image),image\u结束;
std::vectorvctImage(图像开始,图像结束);
std::ios_base::binary
是最重要的部分(类似于
fopen/fread
[“rb”]&可能
QFile
也有类似之处)

此外,发布一些示例代码通常有助于获得正确答案


我有解决这个问题的办法。。。正如雷尼克建议的那样,我尝试了他的想法,但失败了,没有太多理解它。。。从逻辑的角度来看,雷克尼克是对的。。。bat事实是,任何使用QT QByteArray、std或mem的字符串操作都会在找到第一个\0字符时停止,QT QString可以毫无问题地完成操作,但当将其转换为c字符串(char*)时,数据将再次用第一个\0字符进行修剪

我发现使用QDataStream::readRawData将文件读入给定大小的char*中。这就是我完成交易的方式

QFile file("test.pdf");
file.open(QIODevice::ReadOnly);

int         size   = file.size();
char*       buffer = new char[size];    
QDataStream stream(&file);
stream.readRawData(buffer, size);

soap_set_mime(this, "MIME_boundary", NULL);
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
{
    soap_clr_mime(this);

    soapMessage = this->error;
}
请注意

if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
我仍然在使用size变量,而不是使用sizeof(buffer)或任何其他方法,因为这将在找到第一个\0时再次修剪数据

希望这有助于


David G Ortega

你好,雷尼克,fread()对我不起作用,我几乎尝试过任何实现。你介意给我指一段代码吗?非常感谢上面的fread()超链接中提供的示例代码应该读取整个文件并将其放入缓冲区。一旦有了缓冲区,就不要使用字符串操作函数(任何以
str
开头的函数)。您可以使用
mem
函数(memcpy()等),因为它们完全忽略了“\0”嗨,雷尼克,我试过这个。。。没有运气。。。我正在使用pdf,输出更大,pdf已损坏。。。知道为什么吗?它能正确处理小文件吗?首先尝试使用小于64K的图像。嗨,Eugen,谢谢你的回复。我在QT上很熟练,我有自己的调试器,这个国王的应用程序,因为我主要是开发使用FC++和JavaScript使用QTScript和WebKIT的刮板、机器人和混合应用程序。我在调试器中看到,数据由QString保存,没有任何问题,但使用任何QByteArray转换或toStd(W)字符串修剪数据。问题是gsoap在mime响应时只使用char*。。。任何使用STD或ANSI的C++处理都不起作用…至少现在对我来说;)有什么想法吗?在这个回复中,我似乎发现了char*和C字符串之间的混淆。char*仅按约定是字符串。如果您尊重“\0”,则它是一个C字符串。否则,它只是内存缓冲区的地址。因此,我建议您避免使用遵守约定的代码。您的代码(或gSOAP)必须在某个时刻进行MIME转换。这一定有一个功能。你能把指向内存缓冲区的指针传递给这个函数而不做任何转换吗?关于混淆部分:我想看看当转换为char*时,数组是如何被修剪的。如果在调试器中查看、打印或在字符*上执行strlen,它将被视为C字符串,因此可能会被修剪。大卫谈到了这一部分。“以二进制部分打开文件”对我来说似乎很重要,因为在读取时可能会得到EOL转换-现在我想起来了,不明白如何将其视为对第一个\0的修剪。。。我完全同意将字符串函数与“一串字符”数据一起使用会导致一些意外行为我只是简单地说
QFile file("test.pdf");
file.open(QIODevice::ReadOnly);

int         size   = file.size();
char*       buffer = new char[size];    
QDataStream stream(&file);
stream.readRawData(buffer, size);

soap_set_mime(this, "MIME_boundary", NULL);
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
{
    soap_clr_mime(this);

    soapMessage = this->error;
}
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))