From cec99caa47ff1692dd95a85e716f751620f7bef8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Apr 2014 13:45:30 -0700 Subject: [PATCH 1/6] Added upload progress tracking to AccountManager via JSON --- libraries/shared/src/AccountManager.cpp | 12 +++++++++--- libraries/shared/src/AccountManager.h | 5 ++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index 955ba779d1..841fd9dde0 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -170,12 +170,18 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager:: if (!callbackParams.isEmpty()) { // if we have information for a callback, insert the callbackParams into our local map _pendingCallbackMap.insert(networkReply, callbackParams); + + if (callbackParams.updateReciever && !callbackParams.updateSlot.isEmpty()) { + callbackParams.updateReciever->connect(networkReply, SIGNAL(uploadProgress(qint64, qint64)), + callbackParams.updateSlot.toStdString().c_str()); + } } // if we ended up firing of a request, hook up to it now - connect(networkReply, SIGNAL(finished()), this, SLOT(passSuccessToCallback())); + connect(networkReply, SIGNAL(finished()), + SLOT(passSuccessToCallback())); connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)), - this, SLOT(passErrorToCallback(QNetworkReply::NetworkError))); + SLOT(passErrorToCallback(QNetworkReply::NetworkError))); } } } @@ -194,7 +200,7 @@ void AccountManager::passSuccessToCallback() { // remove the related reply-callback group from the map _pendingCallbackMap.remove(requestReply); - } else { + } else { if (VERBOSE_HTTP_REQUEST_DEBUGGING) { qDebug() << "Received JSON response from data-server that has no matching callback."; qDebug() << jsonResponse; diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index bfe84f392e..b410885705 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -21,7 +21,8 @@ class JSONCallbackParameters { public: JSONCallbackParameters() : jsonCallbackReceiver(NULL), jsonCallbackMethod(), - errorCallbackReceiver(NULL), errorCallbackMethod() {}; + errorCallbackReceiver(NULL), errorCallbackMethod(), + updateReciever(NULL), updateSlot() {}; bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; } @@ -29,6 +30,8 @@ public: QString jsonCallbackMethod; QObject* errorCallbackReceiver; QString errorCallbackMethod; + QObject* updateReciever; + QString updateSlot; }; class AccountManager : public QObject { From b21fe02fa2ae017520d6e4a6e05a5e371286bcaf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Apr 2014 13:46:38 -0700 Subject: [PATCH 2/6] Put ModelUploder on a different thread, not to block the rendering of the main window --- interface/src/Application.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d54cceb245..fb50f647e8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3245,9 +3245,12 @@ void Application::toggleRunningScriptsWidget() void Application::uploadFST(bool isHead) { ModelUploader* uploader = new ModelUploader(isHead); - if (uploader->zip()) { - uploader->send(); - } + QThread* thread = new QThread(); + thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit())); + thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater())); + uploader->connect(thread, SIGNAL(started()), SLOT(send())); + + thread->start(); } void Application::uploadHead() { From e85703d25bf657f3a5d7297a38dfe73a5827be04 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Apr 2014 13:48:28 -0700 Subject: [PATCH 3/6] Added feedback and a better success check --- libraries/shared/src/ModelUploader.cpp | 102 +++++++++++++++++++++---- libraries/shared/src/ModelUploader.h | 25 +++++- 2 files changed, 109 insertions(+), 18 deletions(-) diff --git a/libraries/shared/src/ModelUploader.cpp b/libraries/shared/src/ModelUploader.cpp index 71514c8b0f..2ec199750f 100644 --- a/libraries/shared/src/ModelUploader.cpp +++ b/libraries/shared/src/ModelUploader.cpp @@ -9,13 +9,15 @@ #include #include -#include #include -#include +#include #include -#include -#include #include +#include +#include +#include +#include +#include #include "AccountManager.h" #include "ModelUploader.h" @@ -26,9 +28,12 @@ static const QString FILENAME_FIELD = "filename"; static const QString TEXDIR_FIELD = "texdir"; static const QString LOD_FIELD = "lod"; +static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com"; static const QString MODEL_URL = "/api/v1/models"; static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB +static const int TIMEOUT = 1000; +static const int MAX_CHECK = 30; // Class providing the QObject parent system to QTemporaryDir class TemporaryDir : public QTemporaryDir, public QObject { @@ -45,10 +50,11 @@ ModelUploader::ModelUploader(bool isHead) : _totalSize(0), _isHead(isHead), _readyToSend(false), - _dataMultiPart(new QHttpMultiPart(QHttpMultiPart::FormDataType)) + _dataMultiPart(new QHttpMultiPart(QHttpMultiPart::FormDataType)), + _numberOfChecks(MAX_CHECK) { _zipDir->setParent(_dataMultiPart); - + connect(&_timer, SIGNAL(timeout()), SLOT(checkS3())); } ModelUploader::~ModelUploader() { @@ -59,8 +65,9 @@ bool ModelUploader::zip() { // File Dialog QString filename = QFileDialog::getOpenFileName(NULL, "Select your .fst file ...", - QStandardPaths::writableLocation(QStandardPaths::DownloadLocation), + QStandardPaths::writableLocation(QStandardPaths::HomeLocation), "*.fst"); + qDebug() << QStandardPaths::writableLocation(QStandardPaths::HomeLocation); if (filename == "") { // If the user canceled we return. return false; @@ -103,6 +110,7 @@ bool ModelUploader::zip() { " name=\"model_name\""); textPart.setBody(line[1].toUtf8()); _dataMultiPart->append(textPart); + _url = S3_URL + ((_isHead)? "/models/heads/" : "/models/skeletons/") + line[1].toUtf8() + ".fst"; } else if (line[0] == FILENAME_FIELD) { QFileInfo fbx(QFileInfo(fst).path() + "/" + line[1]); if (!fbx.exists() || !fbx.isFile()) { // Check existence @@ -167,9 +175,9 @@ bool ModelUploader::zip() { return true; } -bool ModelUploader::send() { - if (!_readyToSend) { - return false; +void ModelUploader::send() { + if (!zip()) { + return; } JSONCallbackParameters callbackParams; @@ -177,22 +185,52 @@ bool ModelUploader::send() { callbackParams.jsonCallbackMethod = "uploadSuccess"; callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "uploadFailed"; + callbackParams.updateReciever = this; + callbackParams.updateSlot = SLOT(uploadUpdate(qint64, qint64)); AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, callbackParams, QByteArray(), _dataMultiPart); _zipDir = NULL; _dataMultiPart = NULL; qDebug() << "Sending model..."; + _progressDialog = new QDialog(); + _progressBar = new QProgressBar(_progressDialog); + _progressBar->setRange(0, 100); + _progressBar->setValue(0); - return true; + _progressDialog->setWindowTitle("Uploading model..."); + _progressDialog->setLayout(new QGridLayout(_progressDialog)); + _progressDialog->layout()->addWidget(_progressBar); + + _progressDialog->exec(); + + delete _progressDialog; + _progressDialog = NULL; + _progressBar = NULL; +} + +void ModelUploader::uploadUpdate(qint64 bytesSent, qint64 bytesTotal) { + if (_progressDialog) { + _progressBar->setRange(0, bytesTotal); + _progressBar->setValue(bytesSent); + } } void ModelUploader::uploadSuccess(const QJsonObject& jsonResponse) { - qDebug() << "Model sent with success to the data server."; - qDebug() << "It might take a few minute for it to appear in your model browser."; - deleteLater(); + if (_progressDialog) { + _progressDialog->accept(); + } + QMessageBox::information(NULL, + QString("ModelUploader::uploadSuccess()"), + QString("Your model is being processed by the system."), + QMessageBox::Ok); + qDebug() << "Model sent with success"; + checkS3(); } void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString) { + if (_progressDialog) { + _progressDialog->reject(); + } QMessageBox::warning(NULL, QString("ModelUploader::uploadFailed()"), QString("Model could not be sent to the data server."), @@ -201,6 +239,42 @@ void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QS deleteLater(); } +void ModelUploader::checkS3() { + qDebug() << "Checking S3 for " << _url; + QNetworkRequest request(_url); + QNetworkReply* reply = _networkAccessManager.head(request); + connect(reply, SIGNAL(finished()), SLOT(processCheck())); +} + +void ModelUploader::processCheck() { + QNetworkReply* reply = static_cast(sender()); + _timer.stop(); + + switch (reply->error()) { + case QNetworkReply::NoError: + QMessageBox::information(NULL, + QString("ModelUploader::processCheck()"), + QString("Your model is now available in the browser."), + QMessageBox::Ok); + deleteLater(); + break; + case QNetworkReply::ContentNotFoundError: + if (--_numberOfChecks) { + _timer.start(TIMEOUT); + break; + } + default: + QMessageBox::warning(NULL, + QString("ModelUploader::processCheck()"), + QString("Could not verify that the model is present on the server."), + QMessageBox::Ok); + deleteLater(); + break; + } + + delete reply; +} + bool ModelUploader::addTextures(const QFileInfo& texdir) { QStringList filter; filter << "*.png" << "*.tif" << "*.jpg" << "*.jpeg"; diff --git a/libraries/shared/src/ModelUploader.h b/libraries/shared/src/ModelUploader.h index f127008f44..066a577e57 100644 --- a/libraries/shared/src/ModelUploader.h +++ b/libraries/shared/src/ModelUploader.h @@ -10,9 +10,14 @@ #ifndef __hifi__ModelUploader__ #define __hifi__ModelUploader__ -class TemporaryDir; -class QHttpMultiPart; +#include + +class QDialog; class QFileInfo; +class QHttpMultiPart; +class QProgressBar; + +class TemporaryDir; class ModelUploader : public QObject { Q_OBJECT @@ -21,14 +26,18 @@ public: ModelUploader(bool isHead); ~ModelUploader(); - bool zip(); - bool send(); +public slots: + void send(); private slots: + void uploadUpdate(qint64 bytesSent, qint64 bytesTotal); void uploadSuccess(const QJsonObject& jsonResponse); void uploadFailed(QNetworkReply::NetworkError errorCode, const QString& errorString); + void checkS3(); + void processCheck(); private: + QString _url; TemporaryDir* _zipDir; int _lodCount; int _texturesCount; @@ -37,8 +46,16 @@ private: bool _readyToSend; QHttpMultiPart* _dataMultiPart; + QNetworkAccessManager _networkAccessManager; + + int _numberOfChecks; + QTimer _timer; + + QDialog* _progressDialog; + QProgressBar* _progressBar; + bool zip(); bool addTextures(const QFileInfo& texdir); bool compressFile(const QString& inFileName, const QString& outFileName); bool addPart(const QString& path, const QString& name); From 262c6d320640a168894593764d612934e156a969 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Apr 2014 14:35:13 -0700 Subject: [PATCH 4/6] Fixed double JSON callback when http error occurs --- libraries/shared/src/AccountManager.cpp | 25 +++++++++++++++---------- libraries/shared/src/AccountManager.h | 6 ++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index 841fd9dde0..fe361ba751 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -179,15 +179,23 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager:: // if we ended up firing of a request, hook up to it now connect(networkReply, SIGNAL(finished()), - SLOT(passSuccessToCallback())); - connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)), - SLOT(passErrorToCallback(QNetworkReply::NetworkError))); + SLOT(processReply())); } } } -void AccountManager::passSuccessToCallback() { +void AccountManager::processReply() { QNetworkReply* requestReply = reinterpret_cast(sender()); + + if (requestReply->error() == QNetworkReply::NoError) { + passSuccessToCallback(requestReply); + } else { + passErrorToCallback(requestReply); + } + delete requestReply; +} + +void AccountManager::passSuccessToCallback(QNetworkReply* requestReply) { QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll()); JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply); @@ -206,17 +214,15 @@ void AccountManager::passSuccessToCallback() { qDebug() << jsonResponse; } } - delete requestReply; } -void AccountManager::passErrorToCallback(QNetworkReply::NetworkError errorCode) { - QNetworkReply* requestReply = reinterpret_cast(sender()); +void AccountManager::passErrorToCallback(QNetworkReply* requestReply) { JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply); if (callbackParams.errorCallbackReceiver) { // invoke the right method on the callback receiver QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod), - Q_ARG(QNetworkReply::NetworkError, errorCode), + Q_ARG(QNetworkReply::NetworkError, requestReply->error()), Q_ARG(const QString&, requestReply->errorString())); // remove the related reply-callback group from the map @@ -224,10 +230,9 @@ void AccountManager::passErrorToCallback(QNetworkReply::NetworkError errorCode) } else { if (VERBOSE_HTTP_REQUEST_DEBUGGING) { qDebug() << "Received error response from data-server that has no matching callback."; - qDebug() << "Error" << errorCode << "-" << requestReply->errorString(); + qDebug() << "Error" << requestReply->error() << "-" << requestReply->errorString(); } } - delete requestReply; } bool AccountManager::hasValidAccessToken() { diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index b410885705..55a40438e0 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -73,13 +73,15 @@ signals: void loginComplete(const QUrl& authURL); void logoutComplete(); private slots: - void passSuccessToCallback(); - void passErrorToCallback(QNetworkReply::NetworkError errorCode); + void processReply(); private: AccountManager(); AccountManager(AccountManager const& other); // not implemented void operator=(AccountManager const& other); // not implemented + void passSuccessToCallback(QNetworkReply* reply); + void passErrorToCallback(QNetworkReply* reply); + Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation, const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray, From 3be2319081ec99d0df4997cfb95e6eecbb2baa59 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Apr 2014 16:18:23 -0700 Subject: [PATCH 5/6] Removed all the temporaryDir junk --- libraries/shared/src/ModelUploader.cpp | 77 +++++--------------------- libraries/shared/src/ModelUploader.h | 2 - 2 files changed, 14 insertions(+), 65 deletions(-) diff --git a/libraries/shared/src/ModelUploader.cpp b/libraries/shared/src/ModelUploader.cpp index 2ec199750f..cda57aeab9 100644 --- a/libraries/shared/src/ModelUploader.cpp +++ b/libraries/shared/src/ModelUploader.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -35,16 +34,8 @@ static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB static const int TIMEOUT = 1000; static const int MAX_CHECK = 30; -// Class providing the QObject parent system to QTemporaryDir -class TemporaryDir : public QTemporaryDir, public QObject { -public: - virtual ~TemporaryDir() { - // ensuring the entire object gets deleted by the QObject parent. - } -}; ModelUploader::ModelUploader(bool isHead) : - _zipDir(new TemporaryDir()), _lodCount(-1), _texturesCount(-1), _totalSize(0), @@ -53,7 +44,6 @@ ModelUploader::ModelUploader(bool isHead) : _dataMultiPart(new QHttpMultiPart(QHttpMultiPart::FormDataType)), _numberOfChecks(MAX_CHECK) { - _zipDir->setParent(_dataMultiPart); connect(&_timer, SIGNAL(timeout()), SLOT(checkS3())); } @@ -86,11 +76,7 @@ bool ModelUploader::zip() { qDebug() << "Reading FST file : " << QFileInfo(fst).filePath(); // Compress and copy the fst - if (!compressFile(QFileInfo(fst).filePath(), _zipDir->path() + "/" + QFileInfo(fst).fileName())) { - return false; - } - if (!addPart(_zipDir->path() + "/" + QFileInfo(fst).fileName(), - QString("fst"))) { + if (!addPart(QFileInfo(fst).filePath(), QString("fst"))) { return false; } @@ -122,10 +108,7 @@ bool ModelUploader::zip() { return false; } // Compress and copy - if (!compressFile(fbx.filePath(), _zipDir->path() + "/" + line[1])) { - return false; - } - if (!addPart(_zipDir->path() + "/" + line[1], "fbx")) { + if (!addPart(fbx.filePath(), "fbx")) { return false; } } else if (line[0] == TEXDIR_FIELD) { // Check existence @@ -152,10 +135,7 @@ bool ModelUploader::zip() { return false; } // Compress and copy - if (!compressFile(lod.filePath(), _zipDir->path() + "/" + line[1])) { - return false; - } - if (!addPart(_zipDir->path() + "/" + line[1], QString("lod%1").arg(++_lodCount))) { + if (!addPart(lod.filePath(), QString("lod%1").arg(++_lodCount))) { return false; } } @@ -189,7 +169,6 @@ void ModelUploader::send() { callbackParams.updateSlot = SLOT(uploadUpdate(qint64, qint64)); AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, callbackParams, QByteArray(), _dataMultiPart); - _zipDir = NULL; _dataMultiPart = NULL; qDebug() << "Sending model..."; _progressDialog = new QDialog(); @@ -287,11 +266,7 @@ bool ModelUploader::addTextures(const QFileInfo& texdir) { foreach (QFileInfo info, list) { if (info.isFile()) { // Compress and copy - if (!compressFile(info.filePath(), _zipDir->path() + "/" + info.fileName())) { - return false; - } - if (!addPart(_zipDir->path() + "/" + info.fileName(), - QString("texture%1").arg(++_texturesCount))) { + if (!addPart(info.filePath(), QString("texture%1").arg(++_texturesCount))) { return false; } } else if (info.isDir()) { @@ -304,54 +279,30 @@ bool ModelUploader::addTextures(const QFileInfo& texdir) { return true; } -bool ModelUploader::compressFile(const QString &inFileName, const QString &outFileName) { - QFile inFile(inFileName); - inFile.open(QIODevice::ReadOnly); - QByteArray buffer = inFile.readAll(); - - QFile outFile(outFileName); - if (!outFile.open(QIODevice::WriteOnly)) { - QDir(_zipDir->path()).mkpath(QFileInfo(outFileName).path()); - if (!outFile.open(QIODevice::WriteOnly)) { - QMessageBox::warning(NULL, - QString("ModelUploader::compressFile()"), - QString("Could not compress %1").arg(inFileName), - QMessageBox::Ok); - qDebug() << "[Warning] " << QString("Could not compress %1").arg(inFileName); - return false; - } - } - QDataStream out(&outFile); - out << qCompress(buffer); - - return true; -} - - bool ModelUploader::addPart(const QString &path, const QString& name) { - QFile* file = new QFile(path); - if (!file->open(QIODevice::ReadOnly)) { + QFile file(path); + if (!file.open(QIODevice::ReadOnly)) { QMessageBox::warning(NULL, QString("ModelUploader::addPart()"), QString("Could not open %1").arg(path), QMessageBox::Ok); qDebug() << "[Warning] " << QString("Could not open %1").arg(path); - delete file; return false; } + QByteArray buffer = qCompress(file.readAll()); + buffer.remove(0, 4); QHttpPart part; - part.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" + part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data;" " name=\"" + name.toUtf8() + "\";" - " filename=\"" + QFileInfo(*file).fileName().toUtf8() + "\""); - part.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); - part.setBodyDevice(file); + " filename=\"" + QFileInfo(file).fileName().toUtf8() + "\"")); + part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream")); + part.setBody(buffer); _dataMultiPart->append(part); - file->setParent(_dataMultiPart); - qDebug() << "File " << QFileInfo(*file).fileName() << " added to model."; - _totalSize += file->size(); + qDebug() << "File " << QFileInfo(file).fileName() << " added to model."; + _totalSize += file.size(); if (_totalSize > MAX_SIZE) { QMessageBox::warning(NULL, QString("ModelUploader::zip()"), diff --git a/libraries/shared/src/ModelUploader.h b/libraries/shared/src/ModelUploader.h index 066a577e57..0e62ab8705 100644 --- a/libraries/shared/src/ModelUploader.h +++ b/libraries/shared/src/ModelUploader.h @@ -38,7 +38,6 @@ private slots: private: QString _url; - TemporaryDir* _zipDir; int _lodCount; int _texturesCount; int _totalSize; @@ -57,7 +56,6 @@ private: bool zip(); bool addTextures(const QFileInfo& texdir); - bool compressFile(const QString& inFileName, const QString& outFileName); bool addPart(const QString& path, const QString& name); }; From e1a1ff39887152e21aea3f394eb64cc51f3d56c0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 8 Apr 2014 10:32:49 -0700 Subject: [PATCH 6/6] Code review --- libraries/shared/src/AccountManager.cpp | 15 ++++++++++++--- libraries/shared/src/AccountManager.h | 5 +---- libraries/shared/src/ModelUploader.cpp | 7 ++++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index fe361ba751..d284640924 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -34,6 +34,16 @@ Q_DECLARE_METATYPE(JSONCallbackParameters) const QString ACCOUNTS_GROUP = "accounts"; +JSONCallbackParameters::JSONCallbackParameters() : + jsonCallbackReceiver(NULL), + jsonCallbackMethod(), + errorCallbackReceiver(NULL), + errorCallbackMethod(), + updateReciever(NULL), + updateSlot() +{ +} + AccountManager::AccountManager() : _authURL(), _networkAccessManager(NULL), @@ -178,8 +188,7 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager:: } // if we ended up firing of a request, hook up to it now - connect(networkReply, SIGNAL(finished()), - SLOT(processReply())); + connect(networkReply, SIGNAL(finished()), SLOT(processReply())); } } } @@ -208,7 +217,7 @@ void AccountManager::passSuccessToCallback(QNetworkReply* requestReply) { // remove the related reply-callback group from the map _pendingCallbackMap.remove(requestReply); - } else { + } else { if (VERBOSE_HTTP_REQUEST_DEBUGGING) { qDebug() << "Received JSON response from data-server that has no matching callback."; qDebug() << jsonResponse; diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index 55a40438e0..05a2e6a08a 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -19,10 +19,7 @@ class JSONCallbackParameters { public: - JSONCallbackParameters() : - jsonCallbackReceiver(NULL), jsonCallbackMethod(), - errorCallbackReceiver(NULL), errorCallbackMethod(), - updateReciever(NULL), updateSlot() {}; + JSONCallbackParameters(); bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; } diff --git a/libraries/shared/src/ModelUploader.cpp b/libraries/shared/src/ModelUploader.cpp index cda57aeab9..4386704559 100644 --- a/libraries/shared/src/ModelUploader.cpp +++ b/libraries/shared/src/ModelUploader.cpp @@ -34,6 +34,8 @@ static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB static const int TIMEOUT = 1000; static const int MAX_CHECK = 30; +static const int QCOMPRESS_HEADER_POSITION = 0; +static const int QCOMPRESS_HEADER_SIZE = 4; ModelUploader::ModelUploader(bool isHead) : _lodCount(-1), @@ -290,7 +292,10 @@ bool ModelUploader::addPart(const QString &path, const QString& name) { return false; } QByteArray buffer = qCompress(file.readAll()); - buffer.remove(0, 4); + + // Qt's qCompress() default compression level (-1) is the standard zLib compression. + // Here remove Qt's custom header that prevent the data server from uncompressing the files with zLib. + buffer.remove(QCOMPRESS_HEADER_POSITION, QCOMPRESS_HEADER_SIZE); QHttpPart part; part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data;"