QNetworkAccessManager 读取传出数据并将其保存在 QIODevice

Posted

技术标签:

【中文标题】QNetworkAccessManager 读取传出数据并将其保存在 QIODevice【英文标题】:QNetworkAccessManager read outgoingData and keep it in QIODevice 【发布时间】:2011-03-27 16:29:59 【问题描述】:

我正在尝试将所有传出的 POST 数据保存在 QtWebKit 中。

我使用重写 QNetworkReply *QNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice outgoingData) 方法并读取包含传出 POST 数据的传出数据。

问题是读取后,数据在QIODevice中变得不可用。

如何保存传出(PUT、POST)数据并使其可用于未来的内部 Qt 操作?

如果我需要使用其他方法来保存 PUT/POST 数据 - 请告诉我。

代码示例:

QNetworkReply *MyNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
     
 QByteArray bArray = outgoingData->readAll();
 // save bArray (that contains POST outgoing data) somewhere
 // do other things, and outgoingData now has no data anymore, as it was already read to bArray 

我试过了

QByteArray bArray = outgoingData->readAll();
outgoingData->write(bArray);
qDebug() << bArray;

但在这种情况下,我收到“QIODevice::write: ReadOnly device”消息。

如何在 Qt 中保存传出的 POST/PUT 数据?

谢谢。

【问题讨论】:

您能否在您的问题中添加有关您需要这些数据用于什么目的的信息?给我们更广阔的视野。 【参考方案1】:

qint64 QIODevice::peek (char * data, qint64 maxSize)

最多从 设备转化为数据,无副作用 (即,如果您在之后调用 read() peek(),你会得到相同的数据)。 返回读取的字节数。如果 发生错误,例如当 试图窥视打开的设备 WriteOnly 模式,此函数返回 -1.

当没有更多数据时返回0 可供阅读。

编辑

忘记 peak(),在这种情况下不好。您可以使用它,但您必须做很多工作才能完成您的要求。而是阅读Tee is for Tubes,从那里获取代码并使用它。

链接由 peppe 提供,来自http://irc.freenode.net 的#qt irc 频道。 我要感谢 peppethiago,他们非常好心地在#qt 频道上与我讨论这个问题。

如果有一天您想窃取来自 QNetworkAccessManager 的传入(而不是传出)数据,您可以在 How to read data from QNetworkReply being used by QWebPage? 问题中找到答案和代码。

【讨论】:

看起来是一个正确的解决方案,我做的输出数据->peek(100000);我尝试使用输出数据->size() 获取 maxSize,但它始终返回 0。如何获取数据的确切 maxSize?还是随机的大数就可以了? @izyda 我不确定我写这篇文章时的意思,但现在考虑这个问题似乎是 a) 何时到 peek,因为 QtWebKit 可以随时读取数据(参考作为问题中的内部Qt操作)和b)如何跟踪偷看的内容,或者换句话说,如何在偷看的数据和从QIODevice中读取并仍然存在的数据之间保持同步.基本上要做到这一点,您必须创建与我的答案编辑中提到的Grantlee::Tee 非常相似的东西。 对 - 所以考虑到我最感兴趣的是读取传入的数据,我最好继承 QNetworkReply 并在 QWebPage 获取数据之前从那里读取数据......【参考方案2】:

在这种特殊情况下,使用 pos() 和 seek() 实际上不起作用。使用 peek() 的想法似乎要好得多。但是一个例子会很有帮助。所以,这里有一个示例,说明如何在函数 createRequest() 中从给定 QIODevice 的传出数据中获取数据缓冲区,而不影响原始数据。

if (outgoing != NULL)

    const qint64 delta = 100;

    qint64 length = delta;
    QByteArray array;

    while (true)
    
        char *buffer = new char[length];
        qint64 count = outgoing->peek(buffer, length);

        if (count < length)
        
            array = QByteArray(buffer, count);
            delete buffer;
            break;
        

        length += delta;
        delete buffer;
    

为了优化,您可以调整 'delta' 的值。

【讨论】:

效率较低,因为第一段可能会被多次读取。【参考方案3】:

使用 QIODevice::pos() 保存 IO 设备标记。从中读取数据。然后用QIODevice::seek()恢复标记。

这只有在设备是随机访问设备时才有效。但我认为它涵盖了大部分。

【讨论】:

IO 设备是顺序的。 pos() 总是返回 0

以上是关于QNetworkAccessManager 读取传出数据并将其保存在 QIODevice的主要内容,如果未能解决你的问题,请参考以下文章

QNetworkAccessManager:从串行 QIODevice 发布 http 多部分

QNetworkAccessManager 用 url 打开一个 json 数据

错误:没有用于调用“QNetworkAccessManager::QNetworkAccessManager(Networking* const)”的匹配函数

QNetworkAccessManager 问题

使用 QNetworkAccessManager 请求

如何恢复 QNetworkAccessManager