如何制作自己的自定义QNetworkReply?

时间:2018-02-01 18:54:44

标签: windows-10 qt5 qwebview qnetworkaccessmanager qnetworkreply

我一直在尝试创建自己的自定义QNetworkReply类,它从回复中返回自定义字节。我确实从我的QNetworkAccessManager :: createRequest()重载返回该类,我也做了重载。我的问题是,我的函数重载都没有被调用,因此QWebView的请求失败,因为回复是“损坏的”。我试图从Qt测试lib FakeReply中获取一些灵感,但我没有让我的工作。

这是我的代码:

class FakeReply : public QNetworkReply
{
    Q_OBJECT

public:
    FakeReply(const QNetworkRequest& request, QByteArray &data, QObject* parent = 0);
    ~FakeReply();
    QByteArray readAll();
    QByteArray read(qint64 maxSize);
    qint64 peek(char *buffer, qint64 maxlen);
    QByteArray peek(qint64 maxLen);
    qint64 size() const;
    virtual qint64 bytesAvailable() const;
    bool isFinished() const;
    virtual void abort();
    virtual void close();
    bool isSequential() const;
protected:
    qint64 readData(char*, qint64) override;
private:
    QByteArray data;
};

.cpp文件:

FakeReply::FakeReply(const QNetworkRequest &request, QByteArray &bytes, QObject *parent)
    : QNetworkReply(parent),
      data(bytes)
{
    setOperation(QNetworkAccessManager::GetOperation);
    setRequest(request);
    setUrl(request.url());
    open(QIODevice::ReadOnly);
    setFinished(true);
    emit finished();
}

FakeReply::~FakeReply()
{
    close();
}

QByteArray FakeReply::readAll()
{
    qDebug() << "FakeReply::readAll() got called!";
    size_t len = data.length();
    const char *bytes = static_cast<const char*>(data.data());
    char *buffer = static_cast<char*>(malloc(len));
    ASSERT(buffer != NULL, "run out of memory");
    memcpy(buffer, bytes, len);
    QByteArray output;
    output.setRawData(buffer, len);
    data = data.remove(0, len);
    return output;
}

QByteArray FakeReply::read(qint64 maxSize)
{
    qDebug() << "QByteArray FakeReply::read() got called!";
    static char* buffer = nullptr;
    if(bytesAvailable() == 0) {
        return QByteArray();
    }
    size_t len = computeMaxNumberOfBytes(maxSize);
    if(buffer != nullptr) {
        free(buffer);
    }
    buffer = static_cast<char*>(malloc(len));
    ASSERT(buffer != NULL, "run out of memory");
    memcpy(buffer, data.data(), len);
    data = data.remove(0, len);
    QByteArray output;
    output.setRawData(buffer, len);
    return output;
}

qint64 FakeReply::peek(char *buffer, qint64 maxlen)
{
    qDebug() << "FakeReply::peek() got called!";
    size_t len = computeMaxNumberOfBytes(maxlen);
    memcpy(buffer, data.data(), len);
    return static_cast<qint64>(len);
}

QByteArray FakeReply::peek(qint64 maxlen)
{
    qDebug() << "FakeReply::peek(qint64 maxlen) got called!";
    QByteArray output;
    output.setRawData(data.data(), computeMaxNumberOfBytes(maxlen));
    return output;
}

qint64 FakeReply::size() const
{
    return data.length();
}

qint64 FakeReply::bytesAvailable() const
{
    qDebug() << "FakeReply::bytesAvailable()";
    return data.length();
}

bool FakeReply::isFinished() const
{
    qDebug() << "FakeReply::isFinished() got called!";
    return true;
}

void FakeReply::abort()
{
    qDebug() << "FakeReply::abort() got called!";
}

void FakeReply::close()
{
    qDebug() << "FakeReply::close() got called!";
}

bool FakeReply::isSequential() const
{
    qDebug() << "FakeReply::isSequential() const got called!";
    return false;
}

qint64 FakeReply::readData(char *, qint64)
{
    qDebug() << "FakeReply::readData() got called!";
    return 0;
}

这个类的用法如下:

QNetworkReply *MyNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
{
     QString path = request.url().path();
    QNetworkReply *reply = QNetworkAccessManager::createRequest(op, request, outgoingData);

     if(path == QStringLiteral("/testing")) {
         QByteArray response = waitThenReadAll(reply);
         return new FakeReply(request, response);
     }
     return reply;
   }

1 个答案:

答案 0 :(得分:1)

对于有相同问题的任何人,我从here获得了一些代码示例的答案:我在代码中缺少的是我使用emit finish()而不是

QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));

确实有效。