如何制作自己的自定义 QNetworkReply?
How do I make my own custom QNetworkReply?
我一直在尝试创建自己的自定义 QNetworkReply class,其中 return 个来自回复的自定义字节。我从我的 QNetworkAccessManager::createRequest() 重载中执行 return class 我也执行了重载。我的问题是,我的函数重载 none 被调用,因此 QWebView 的请求失败,因为回复是 "corrupted"。我试图从 Qt 测试库的 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;
}
class的用法是这样的:
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;
}
对于任何有同样问题的人,我从 here
的一些代码示例中得到了答案:我的代码中缺少的是我使用的是 emit finish()
而不是
QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));
确实有效。
我一直在尝试创建自己的自定义 QNetworkReply class,其中 return 个来自回复的自定义字节。我从我的 QNetworkAccessManager::createRequest() 重载中执行 return class 我也执行了重载。我的问题是,我的函数重载 none 被调用,因此 QWebView 的请求失败,因为回复是 "corrupted"。我试图从 Qt 测试库的 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;
}
class的用法是这样的:
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;
}
对于任何有同样问题的人,我从 here
的一些代码示例中得到了答案:我的代码中缺少的是我使用的是 emit finish()
而不是
QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));
确实有效。