#pragma once#include <QtNetwork/QNetworkReply>#include <QtCore/QFile>#include <QtCore/QByteArray>#include <QtCore/QThread>class MyNetworkReply : public QNetworkReply, QThread{private: QFile* m_file; QByteArray m_content; qint64 m_offset;public: MyNetworkReply(QObject* parent = 0); ~MyNetworkReply();//QNetworkReplypublic: void abort(); void setConfig(const QUrl&, QNetworkAccessManager::Operation, const QNetworkRequest&);//QIODevicepublic: void run(); qint64 bytesAvailable() const; bool isSequential() const; bool open(OpenMode open);protected: qint64 readData(char* data, qint64 maxSize);};
#include "MyNetworkReply.h"MyNetworkReply::MyNetworkReply(QObject* parent) : QNetworkReply(parent), QThread(){ m_file = new QFile("1.jpg"); this->open(QIODevice::ReadOnly | QIODevice::Unbuffered); m_offset = 0; m_content = m_file->readAll(); this->setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); this->setHeader(QNetworkRequest::ContentLengthHeader, QVariant(m_content.size())); this->start();}MyNetworkReply::~MyNetworkReply(){ this->close(); delete m_file;}void MyNetworkReply::abort(){ this->close();}void MyNetworkReply::setConfig(const QUrl& turl, QNetworkAccessManager::Operation op, const QNetworkRequest& req){ this->setUrl(turl); this->setOperation(op); this->setRequest(req);}qint64 MyNetworkReply::readData(char* data, qint64 maxSize){ if (m_offset < m_content.size()) { qint64 number = qMin(maxSize, m_content.size() - m_offset); memcpy(data, m_content.constData() + m_offset, number); m_offset += number; return number; } else { return -1; }}qint64 MyNetworkReply::bytesAvailable() const{ return m_content.size() - m_offset;}bool MyNetworkReply::isSequential() const{ return true;}bool MyNetworkReply::open(OpenMode open){ QIODevice::setOpenMode(open); return m_file->open(open);}void MyNetworkReply::run(){ while(m_offset == 0) { emit QNetworkReply::readyRead(); emit QNetworkReply::finished(); }}
#pragma once#include <QtNetwork/QNetworkAccessManager>class MyNetworkAccessManager : public QNetworkAccessManager{private: QNetworkReply* createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData = 0);public: MyNetworkAccessManager(); ~MyNetworkAccessManager();};
#include "MyNetworkAccessManager.h"#include "MyNetworkReply.h"MyNetworkAccessManager::MyNetworkAccessManager() : QNetworkAccessManager(){}MyNetworkAccessManager::~MyNetworkAccessManager(){}QNetworkReply* MyNetworkAccessManager::createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData){ MyNetworkReply* networkReply = new MyNetworkReply(this); networkReply->setConfig(req.url(), op, req); return networkReply;}
#include <windows.h>#include <QtGui/QApplication>#include <QtWebKit/QWebView>#include "MyNetworkAccessManager.h"#include "MyNetworkReply.h"#pragma comment (lib, "QtGui4.lib")#pragma comment (lib, "QtCore4.lib")#pragma comment (lib, "qtmain.lib")#pragma comment (lib, "QtNetwork4.lib")#pragma comment (lib, "QtWebKit4.lib")int main(int argc, char* argv[]){ QApplication app(argc, argv); QWebView* webView = new QWebView(); webView->page()->setNetworkAccessManager(new MyNetworkAccessManager()); webView->page()->setForwardUnsupportedContent(true); QWidget::connect(webView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), &app, SLOT(aboutQt())); webView->setHtml("<b>Image:</b><br><img border=\'1\' src=\'files/1.jpg\'>", QUrl("test://test.ru/")); webView->show(); return app.exec();}
C++ (Qt)struct MiniServerResponse{ QString mimeType; QByteArray data; int code; QString errorText;}; class MiniServerNetworkReply : public QNetworkReply {public: explicit MiniServerNetworkReply(const MiniServerResponse &response, QObject * parent = 0); ~MiniServerNetworkReply(); inline qint64 bytesAvailable() const { return data.size() - position; } inline bool isSequential() const { return true; } inline void abort() { }protected: qint64 readData(char *data, qint64 maxlen); qint64 position;private: QByteArray data; QString contentType;}; qint64 MiniServerNetworkReply::readData(char *buffer, qint64 maxlen){ qint64 cnt = qMin(maxlen, bytesAvailable()); const char * slice = data.mid(position, cnt).data(); qstrncpy(buffer, slice, cnt); return cnt;} MiniServerNetworkReply::MiniServerNetworkReply(const MiniServerResponse &response, QObject * parent) : QNetworkReply(parent){ QNetworkReply::open(QIODevice::ReadOnly); position = 0; contentType = response.mimeType; if (response.code==200) { // HTTP 200 is OK data = response.data; } else { QString error = QString("<html><head><title>Error %1</title></head><body><h1>Error %1</h1><p>%2</p></body></html>") .arg(response.code) .arg(response.errorText); data = error.toUtf8(); } setHeader(QNetworkRequest::LastModifiedHeader, QDateTime::currentDateTime()); setHeader(QNetworkRequest::ContentLengthHeader, data.size()); setHeader(QNetworkRequest::ContentTypeHeader, response.mimeType); QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, Q_ARG(qint64, data.size()), Q_ARG(qint64, data.size())); QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);}
C++ (Qt)qint64 MiniServerNetworkReply::readData(char *buffer, qint64 maxlen){ ... const char * slice = data.mid(position, cnt).data(); // Здесь slice указывает на уже разрушенный буфер (то что это работает - случайность, может и не работать или работать не так. :)}