I am attempting to build my own custom QAbstractNetworkCache
implementation for use with QNetworkAccessManager
.
I am having trouble with QAbstractNetworkCache::insert(QIODevice *device)
; inside this method, the device always arrives with 0 bytes to read from.
As I understand, the QIODevice*
that is returned from QAbstractNetworkCache::prepare(const QNetworkCacheMetaData &metaData)
is going to be filled with data and used as a parameter to QAbstractNetworkCache::insert(QIODevice *device)
method once QNetworkAccessManager
finishes downloading.
So I have prepared a QBuffer
to be this container, but whenever QAbstractNetworkCache::insert(QIODevice *device)
is getting called, it always arrives with nothing in it (device->bytesAvailable() == 0)
QIODevice* NetworkCachePrivate::prepare(const QNetworkCacheMetaData &metaData) {
if (!metaData.isValid() || !metaData.url().isValid() || cacheDir.isEmpty()) return 0;
QIODevice* device = 0;
QString hash = hexMD5(metaData.url().toString());
QScopedPointer<QBuffer> buffer(new QBuffer);
if (buffer->open(QIODevice::ReadWrite))
{
qDebug() << "BUFFER READY";
device = buffer.take();
deviceMapping[device] = qMakePair(hash, metaData);
}
return device;
}
void NetworkCachePrivate::insert(QIODevice *device) {
if (deviceMapping.contains(device))
{
QPair<QString, QNetworkCacheMetaData> pair = deviceMapping[device];
QString fileName;
fileName += cacheDir;
fileName += QLatin1String("/");
fileName += pair.first;
qDebug() << "DEVICE BYTES" << device->bytesAvailable(); //ALWAYS 0!!!! :(
QFile file(fileName);
if (file.open(QIODevice::WriteOnly))
{
qint64 size = file.write(device->readAll());
if (size <= 0)
{
file.remove();
}
else
{
qDebug() << "FILE WROTE " << size;
cacheSize += size;
}
}
deviceMapping.remove(device);
delete device;
}
}
QNetworkCacheMetaData NetworkCachePrivate::metaData (const QUrl &url ) {
QString fileName;
fileName += cacheDir;
fileName += QLatin1String("/");
fileName += hexMD5(url.toString());
QNetworkCacheMetaData data;
if (!QFile::exists(fileName))
return data;
data.setUrl(url);
data.setExpirationDate(QDateTime::currentDateTime().addYears(1));
return data;
}
As peppe also pointed out in the comment, you need to seek the QBuffer
to the beginning after the write and before the read as per the documentation:
QBuffer allows you to access a QByteArray using the QIODevice interface. The QByteArray is treated just as a standard random-accessed file. Example:
QBuffer buffer;
char ch;
buffer.open(QBuffer::ReadWrite);
buffer.write("Qt rocks!");
*** buffer.seek(0); ***
buffer.getChar(&ch); // ch == 'Q'
buffer.getChar(&ch); // ch == 't'
buffer.getChar(&ch); // ch == ' '
buffer.getChar(&ch); // ch == 'r'
To be more concrete for your code, you would need to insert the statement like this:
...
device.seek(0);
qDebug() << "DEVICE BYTES" << device->bytesAvailable(); //NOT 0 ANYMORE!!!! :)
...