2

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

我正在开发一个使用 gsoap 的服务。我想回复一个哑剧回复。我一切正常,但是在读取二进制文件时,所有类型的文件(如 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;
    } 

也不起作用

QFile::ReadAll有效,但是在转换QStringchar*数组时会在第一个NUL.

那么,读取整个二进制文件的最佳方法是什么?有时 C++ 是多么疯狂。

提前致谢。

我已经按照 retnick 的建议尝试了这个

    UrlToPdf urlToPdf;  
urlToPdf.getUrl(&input, &result);  

QByteArray raw = urlToPdf.getPdf(QString(result.data.c_str()));  

int   size      = raw.toBase64().size();  
char* arraydata = new char[size];  
strcpy(arraydata, raw.toBase64().data());  

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

    soapMessage = this->error;  
}  

但没有运气... mime 响应比实际文件大...

大卫·G·奥尔特加

4

3 回答 3

2

读取二进制文件使用fread() 读取它后,将其视为字节数组而不是字符串。不允许使用字符串函数。

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

  int soap_set_mime_attachment(struct soap *soap, char *buf_ptr, size_t buf_size, 
        enum soap_mime_encoding encoding, 
        const char *type, const char *id, 
        const char *location, const char *description);

char *buf_ptr是你的缓冲区。 size_t buf_size是缓冲区的长度。

所以只要做你的QFile::ReadAll.

这给了你一个QByteArray. QByteArray 有方法

QByteArray QByteArray::toBase64 () const

这将返回一个

 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); 

我没有对此进行测试,但应该接近完成。

于 2010-06-21T20:38:24.030 回答
1

QFile::ReadAll 有效,但是在将 QString 转换为 char* 时,数组在第一个 NUL 中被修剪。

您确定它实际上已被修剪,或者您无法在调试器中打印/查看数组[因为 C 风格的字符串是 0 终止的]?

如果 QString 本身不足以满足您的需求,您可能希望使用范围构造函数或范围分配将其转换为 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::ios_base::binary是事物中最重要的部分(类似于fopen/fread["rb"] 并且可能QFile有类似的东西)

还发布一些示例代码通常有助于获得正确的答案。

HIH

于 2010-06-21T21:14:32.803 回答
1

我有这个解决方案......正如雷尼克建议的那样,我尝试了他的想法,但它失败了,没有太多理解它......从逻辑的角度来看,雷尼克是正确的......事实是,任何使用字符串操作的国王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 var 而不是 sizeof(buffer) 或任何其他方法,因为这将再次修剪数据 qhen 找到第一个 \0 ...

希望这可以帮助...

大卫·G·奥尔特加

于 2010-07-09T11:52:43.797 回答