Skip to content

Commit

Permalink
Merge branch 'jb50799-image-read' into 'master'
Browse files Browse the repository at this point in the history
[libsocialcache] Convert content type of downloaded image if necessary. Contributes to JB#50799

See merge request mer-core/libsocialcache!12
  • Loading branch information
blam committed Feb 22, 2021
2 parents 8d46699 + 7ead0d5 commit 6c3f563
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 38 deletions.
85 changes: 49 additions & 36 deletions src/lib/abstractimagedownloader.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Lucien Xu <sfietkonstantin@free.fr>
* Copyright (C) 2013 - 2021 Jolla Pty Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -22,7 +23,8 @@
#include <QtCore/QDir>
#include <QtCore/QCryptographicHash>
#include <QtCore/QStandardPaths>
#include <QtGui/QImageReader>
#include <QtCore/QMimeDatabase>
#include <QtGui/QImage>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
Expand Down Expand Up @@ -69,8 +71,8 @@ void AbstractImageDownloaderPrivate::manageStack()
url = info->redirectUrl;
}

info->file.setFileName(q->outputFile(url, info->requestsData.first()));
QDir parentDir = QFileInfo(info->file.fileName()).dir();
info->fileName = q->outputFile(url, info->requestsData.first());
QDir parentDir = QFileInfo(info->fileName).dir();
if (!parentDir.exists()) {
parentDir.mkpath(".");
}
Expand All @@ -96,31 +98,57 @@ void AbstractImageDownloaderPrivate::manageStack()
}
}

static void readData(ImageInfo *info, QNetworkReply *reply)
static bool writeImageData(const QString &localFilePath, QNetworkReply *reply)
{
qint64 bytesAvailable = reply->bytesAvailable();
if (bytesAvailable == 0) {
qWarning() << Q_FUNC_INFO << "No image data available";
return;
return false;
}

QByteArray buf = reply->readAll();
info->file.write(buf);
}

void AbstractImageDownloader::readyRead()
{
Q_D(AbstractImageDownloader);
const QByteArray imageData = reply->readAll();

QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
if (!reply) {
return;
static const QMimeDatabase mimeDatabase;
const QMimeType dataMimeType = mimeDatabase.mimeTypeForData(imageData);
if (!dataMimeType.name().startsWith(QStringLiteral("image/"))) {
qWarning() << "Downloaded file is not an image, mime type is" << dataMimeType.name();
return false;
}

ImageInfo *info = d->runningReplies.value(reply);
if (info) {
readData(info, reply);
const QMimeType localFilePathMimeType = mimeDatabase.mimeTypesForFileName(localFilePath).value(0);

if (localFilePathMimeType != dataMimeType) {
// The destination file path has a file extension that does not match the mime type of the
// downloaded content.
const QFileInfo fileInfo(localFilePath);
qWarning() << "Downloaded file" << fileInfo.fileName() << "has type" << dataMimeType.name()
<< "instead of expected" << localFilePathMimeType.name()
<< ", converting to" << localFilePathMimeType.name();

QImage image;
if (!image.loadFromData(imageData)) {
qWarning() << "Unable to read downloaded image data";
return false;
}

// QImage::save() will convert the image to the correct mime type when writing to file.
if (!image.save(localFilePath)) {
qWarning() << "Unable to save downloaded image data to file:" << localFilePath;
return false;
}
} else {
// The downloaded content matches the mime type of the destination file path, so save the
// content directly to the file without converting it.
QFile file(localFilePath);
if (!file.open(QFile::WriteOnly)) {
qWarning() << "Unable to write downloaded image data to file:" << localFilePath;
return false;
}
file.write(imageData);
file.close();
}

return true;
}

void AbstractImageDownloader::slotFinished()
Expand Down Expand Up @@ -155,28 +183,13 @@ void AbstractImageDownloader::slotFinished()
d->stack.append(info);
d->manageStack();
} else {
if (!info->file.open(QIODevice::ReadWrite)) {
qWarning() << Q_FUNC_INFO << "Failed to open file for write" << info->file.errorString();
Q_FOREACH (const QVariantMap &metadata, info->requestsData) {
emit imageDownloaded(info->url, QString(), metadata);
}
d->manageStack();
return;
}

const QString fileName = info->file.fileName();
readData(info, reply);
info->file.close();

QImageReader reader(fileName);
if (reader.canRead()) {
dbQueueImage(info->url, info->requestsData.first(), fileName);
if (writeImageData(info->fileName, reply)) {
dbQueueImage(info->url, info->requestsData.first(), info->fileName);
Q_FOREACH (const QVariantMap &metadata, info->requestsData) {
emit imageDownloaded(info->url, fileName, metadata);
emit imageDownloaded(info->url, info->fileName, metadata);
}
} else {
// the file is not in image format.
info->file.remove(fileName); // remove artifacts.
Q_FOREACH (const QVariantMap &metadata, info->requestsData) {
emit imageDownloaded(info->url, QString(), metadata);
}
Expand Down
1 change: 0 additions & 1 deletion src/lib/abstractimagedownloader.h
Expand Up @@ -69,7 +69,6 @@ public Q_SLOTS:
QScopedPointer<AbstractImageDownloaderPrivate> d_ptr;

private Q_SLOTS:
void readyRead();
void slotFinished();
void timedOut();

Expand Down
4 changes: 3 additions & 1 deletion src/lib/abstractimagedownloader_p.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 Lucien XU <sfietkonstantin@free.fr>
* Copyright (C) 2013 - 2021 Jolla Pty Ltd.
*
* You may use this file under the terms of the BSD license as follows:
*
Expand Down Expand Up @@ -45,12 +46,13 @@ struct ImageInfo
ImageInfo(const QString &url, const QVariantMap &data) : url(url), requestsData(QList<QVariantMap>() << data) {}

QString url;
QFile file;
QString fileName;
QString redirectUrl;
QList<QVariantMap> requestsData;
};


class QMimeDatabase;
class AbstractImageDownloader;
class AbstractImageDownloaderPrivate
{
Expand Down

0 comments on commit 6c3f563

Please sign in to comment.