mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 16:36:54 +02:00
Upload FST
This commit is contained in:
parent
51585acd25
commit
e5b5778caf
4 changed files with 138 additions and 67 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include <QtCore/QStringList>
|
#include <QtCore/QStringList>
|
||||||
#include <QtCore/QUrlQuery>
|
#include <QtCore/QUrlQuery>
|
||||||
#include <QtNetwork/QNetworkRequest>
|
#include <QtNetwork/QNetworkRequest>
|
||||||
|
#include <QHttpMultiPart>
|
||||||
|
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
#include "PacketHeaders.h"
|
#include "PacketHeaders.h"
|
||||||
|
@ -30,6 +31,7 @@ Q_DECLARE_METATYPE(OAuthAccessToken)
|
||||||
Q_DECLARE_METATYPE(DataServerAccountInfo)
|
Q_DECLARE_METATYPE(DataServerAccountInfo)
|
||||||
Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
|
Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
|
||||||
Q_DECLARE_METATYPE(JSONCallbackParameters)
|
Q_DECLARE_METATYPE(JSONCallbackParameters)
|
||||||
|
Q_DECLARE_METATYPE(QHttpMultiPart)
|
||||||
|
|
||||||
const QString ACCOUNTS_GROUP = "accounts";
|
const QString ACCOUNTS_GROUP = "accounts";
|
||||||
|
|
||||||
|
@ -99,21 +101,25 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||||
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) {
|
const JSONCallbackParameters& callbackParams,
|
||||||
|
const QByteArray& dataByteArray,
|
||||||
|
QHttpMultiPart* dataMultiPart) {
|
||||||
QMetaObject::invokeMethod(this, "invokedRequest",
|
QMetaObject::invokeMethod(this, "invokedRequest",
|
||||||
Q_ARG(const QString&, path),
|
Q_ARG(const QString&, path),
|
||||||
Q_ARG(QNetworkAccessManager::Operation, operation),
|
Q_ARG(QNetworkAccessManager::Operation, operation),
|
||||||
Q_ARG(const JSONCallbackParameters&, callbackParams),
|
Q_ARG(const JSONCallbackParameters&, callbackParams),
|
||||||
Q_ARG(const QByteArray&, dataByteArray));
|
Q_ARG(const QByteArray&, dataByteArray),
|
||||||
|
Q_ARG(QHttpMultiPart*, dataMultiPart));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||||
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) {
|
const JSONCallbackParameters& callbackParams,
|
||||||
|
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
|
||||||
|
|
||||||
if (!_networkAccessManager) {
|
if (!_networkAccessManager) {
|
||||||
_networkAccessManager = new QNetworkAccessManager(this);
|
_networkAccessManager = new QNetworkAccessManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasValidAccessToken()) {
|
if (hasValidAccessToken()) {
|
||||||
QNetworkRequest authenticatedRequest;
|
QNetworkRequest authenticatedRequest;
|
||||||
|
|
||||||
|
@ -140,11 +146,18 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
|
||||||
case QNetworkAccessManager::PostOperation:
|
case QNetworkAccessManager::PostOperation:
|
||||||
case QNetworkAccessManager::PutOperation:
|
case QNetworkAccessManager::PutOperation:
|
||||||
authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
if (dataMultiPart) {
|
||||||
if (operation == QNetworkAccessManager::PostOperation) {
|
if (operation == QNetworkAccessManager::PostOperation) {
|
||||||
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
|
networkReply = _networkAccessManager->post(authenticatedRequest, dataMultiPart);
|
||||||
|
} else {
|
||||||
|
networkReply = _networkAccessManager->put(authenticatedRequest, dataMultiPart);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
|
if (operation == QNetworkAccessManager::PostOperation) {
|
||||||
|
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
|
||||||
|
} else {
|
||||||
|
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -39,7 +39,8 @@ public:
|
||||||
void authenticatedRequest(const QString& path,
|
void authenticatedRequest(const QString& path,
|
||||||
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
|
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
|
||||||
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
|
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
|
||||||
const QByteArray& dataByteArray = QByteArray());
|
const QByteArray& dataByteArray = QByteArray(),
|
||||||
|
QHttpMultiPart* dataMultiPart = NULL);
|
||||||
|
|
||||||
const QUrl& getAuthURL() const { return _authURL; }
|
const QUrl& getAuthURL() const { return _authURL; }
|
||||||
void setAuthURL(const QUrl& authURL);
|
void setAuthURL(const QUrl& authURL);
|
||||||
|
@ -77,7 +78,9 @@ private:
|
||||||
void operator=(AccountManager const& other); // not implemented
|
void operator=(AccountManager const& other); // not implemented
|
||||||
|
|
||||||
Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||||
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray);
|
const JSONCallbackParameters& callbackParams,
|
||||||
|
const QByteArray& dataByteArray,
|
||||||
|
QHttpMultiPart* dataMultiPart);
|
||||||
|
|
||||||
QUrl _authURL;
|
QUrl _authURL;
|
||||||
QNetworkAccessManager* _networkAccessManager;
|
QNetworkAccessManager* _networkAccessManager;
|
||||||
|
|
|
@ -10,15 +10,38 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QDir>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
#include <QHttpMultiPart>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include "AccountManager.h"
|
||||||
|
|
||||||
#include "FstReader.h"
|
#include "FstReader.h"
|
||||||
|
|
||||||
FstReader::FstReader() {
|
|
||||||
|
static const QString NAME_FIELD = "name";
|
||||||
|
static const QString FILENAME_FIELD = "filename";
|
||||||
|
static const QString TEXDIR_FIELD = "texdir";
|
||||||
|
static const QString LOD_FIELD = "lod";
|
||||||
|
|
||||||
|
static const QString MODEL_URL = "/api/v1/models";
|
||||||
|
|
||||||
|
static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||||
|
|
||||||
|
FstReader::FstReader() :
|
||||||
|
_lodCount(-1),
|
||||||
|
_texturesCount(-1),
|
||||||
|
_readyToSend(false),
|
||||||
|
_dataMultiPart(new QHttpMultiPart(QHttpMultiPart::FormDataType))
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FstReader::~FstReader() {
|
||||||
|
if (_dataMultiPart) {
|
||||||
|
delete _dataMultiPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool FstReader::zip() {
|
bool FstReader::zip() {
|
||||||
// File Dialog
|
// File Dialog
|
||||||
|
@ -33,11 +56,18 @@ bool FstReader::zip() {
|
||||||
qDebug() << "[ERROR] Could not open FST file : " << fst.fileName();
|
qDebug() << "[ERROR] Could not open FST file : " << fst.fileName();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compress and copy the fst
|
||||||
|
if (!compressFile(QFileInfo(fst).filePath(), _zipDir.path() + "/" + QFileInfo(fst).fileName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_totalSize += QFileInfo(fst).size();
|
||||||
|
if (!addPart(_zipDir.path() + "/" + QFileInfo(fst).fileName(),
|
||||||
|
QString("fst"))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
qDebug() << "Reading FST file : " << QFileInfo(fst).filePath();
|
qDebug() << "Reading FST file : " << QFileInfo(fst).filePath();
|
||||||
|
|
||||||
|
|
||||||
QDir rootDir(_zipDir.path());
|
|
||||||
|
|
||||||
// Let's read through the FST file
|
// Let's read through the FST file
|
||||||
QTextStream stream(&fst);
|
QTextStream stream(&fst);
|
||||||
QList<QString> line;
|
QList<QString> line;
|
||||||
|
@ -47,20 +77,34 @@ bool FstReader::zip() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_totalSize > MAX_SIZE) {
|
||||||
|
qDebug() << "[ERROR] Model too big, over " << MAX_SIZE << " Bytes.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// according to what is read, we modify the command
|
// according to what is read, we modify the command
|
||||||
if (line.first() == nameField) {
|
if (line.first() == NAME_FIELD) {
|
||||||
_modelName = line[1];
|
QHttpPart textPart;
|
||||||
} else if (line.first() == filenameField) {
|
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
|
||||||
|
" name=\"model_name\"");
|
||||||
|
//textPart.setRawHeader("name", "\"model_name\"");
|
||||||
|
textPart.setBody(line[1].toUtf8());
|
||||||
|
_dataMultiPart->append(textPart);
|
||||||
|
} else if (line.first() == FILENAME_FIELD) {
|
||||||
QFileInfo fbx(QFileInfo(fst).path() + "/" + line[1]);
|
QFileInfo fbx(QFileInfo(fst).path() + "/" + line[1]);
|
||||||
if (!fbx.exists() || !fbx.isFile()) { // Check existence
|
if (!fbx.exists() || !fbx.isFile()) { // Check existence
|
||||||
qDebug() << "[ERROR] FBX file " << fbx.absoluteFilePath() << " doesn't exist.";
|
qDebug() << "[ERROR] FBX file " << fbx.absoluteFilePath() << " doesn't exist.";
|
||||||
return false;
|
return false;
|
||||||
} else { // Compress and copy
|
|
||||||
_fbxFile = rootDir.path() + "/" + line[1];
|
|
||||||
_totalSize += fbx.size();
|
|
||||||
compressFile(fbx.filePath(), _fbxFile);
|
|
||||||
}
|
}
|
||||||
} else if (line.first() == texdirField) { // Check existence
|
// Compress and copy
|
||||||
|
if (!compressFile(fbx.filePath(), _zipDir.path() + "/" + line[1])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_totalSize += fbx.size();
|
||||||
|
if (!addPart(_zipDir.path() + "/" + line[1], "fbx")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (line.first() == TEXDIR_FIELD) { // Check existence
|
||||||
QFileInfo texdir(QFileInfo(fst).path() + "/" + line[1]);
|
QFileInfo texdir(QFileInfo(fst).path() + "/" + line[1]);
|
||||||
if (!texdir.exists() || !texdir.isDir()) {
|
if (!texdir.exists() || !texdir.isDir()) {
|
||||||
qDebug() << "[ERROR] Texture directory " << texdir.absolutePath() << " doesn't exist.";
|
qDebug() << "[ERROR] Texture directory " << texdir.absolutePath() << " doesn't exist.";
|
||||||
|
@ -69,47 +113,41 @@ bool FstReader::zip() {
|
||||||
if (!addTextures(texdir)) { // Recursive compress and copy
|
if (!addTextures(texdir)) { // Recursive compress and copy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (line.first() == lodField) {
|
} else if (line.first() == LOD_FIELD) {
|
||||||
QFileInfo lod(QFileInfo(fst).path() + "/" + line[1]);
|
QFileInfo lod(QFileInfo(fst).path() + "/" + line[1]);
|
||||||
if (!lod.exists() || !lod.isFile()) { // Check existence
|
if (!lod.exists() || !lod.isFile()) { // Check existence
|
||||||
qDebug() << "[ERROR] FBX file " << lod.absoluteFilePath() << " doesn't exist.";
|
qDebug() << "[ERROR] FBX file " << lod.absoluteFilePath() << " doesn't exist.";
|
||||||
//return false;
|
return false;
|
||||||
} else { // Compress and copy
|
}
|
||||||
_lodFiles.push_back(rootDir.path() + "/" + line[1]);
|
// Compress and copy
|
||||||
_totalSize += lod.size();
|
if (!compressFile(lod.filePath(), _zipDir.path() + "/" + line[1])) {
|
||||||
compressFile(lod.filePath(), _lodFiles.back());
|
return false;
|
||||||
|
}
|
||||||
|
_totalSize += lod.size();
|
||||||
|
if (!addPart(_zipDir.path() + "/" + line[1], QString("lod%1").arg(++_lodCount))) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress and copy the fst
|
_readyToSend = true;
|
||||||
_fstFile = rootDir.path() + "/" + QFileInfo(fst).fileName();
|
|
||||||
_totalSize += QFileInfo(fst).size();
|
|
||||||
compressFile(fst.fileName(), _fstFile);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FstReader::send() {
|
bool FstReader::send() {
|
||||||
QString command = QString("curl -F \"model_name=%1\"").arg(_modelName);
|
if (!_readyToSend) {
|
||||||
|
return false;
|
||||||
command += QString(" -F \"fst=@%1\" -F \"fbx=@%2\"").arg(_fstFile, _fbxFile);
|
|
||||||
for (int i = 0; i < _lodFiles.size(); ++i) {
|
|
||||||
command += QString(" -F \"lod%1=@%2\"").arg(i).arg(_lodFiles[i]);
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < _textureFiles.size(); ++i) {
|
|
||||||
command += QString(" -F \"lod%1=@%2\"").arg(i).arg(_textureFiles[i]);
|
|
||||||
}
|
|
||||||
command += " http://localhost:3000/api/v1/models/?access_token\\=017894b7312316a2b5025613fcc58c13bc701da9b797cca34b60aae9d1c53acb --trace-ascii /dev/stdout";
|
|
||||||
|
|
||||||
qDebug() << "[DEBUG] " << command;
|
AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, JSONCallbackParameters(), QByteArray(), _dataMultiPart);
|
||||||
|
|
||||||
|
_dataMultiPart = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FstReader::addTextures(QFileInfo& texdir) {
|
bool FstReader::addTextures(const QFileInfo& texdir) {
|
||||||
QStringList filter;
|
QStringList filter;
|
||||||
filter << "*.png" << "*.tiff" << "*.jpg" << "*.jpeg";
|
filter << "*.png" << "*.tif" << "*.jpg" << "*.jpeg";
|
||||||
|
|
||||||
QFileInfoList list = QDir(texdir.filePath()).entryInfoList(filter,
|
QFileInfoList list = QDir(texdir.filePath()).entryInfoList(filter,
|
||||||
QDir::Files |
|
QDir::Files |
|
||||||
|
@ -118,9 +156,15 @@ bool FstReader::addTextures(QFileInfo& texdir) {
|
||||||
QDir::NoSymLinks);
|
QDir::NoSymLinks);
|
||||||
foreach (QFileInfo info, list) {
|
foreach (QFileInfo info, list) {
|
||||||
if (info.isFile()) {
|
if (info.isFile()) {
|
||||||
_textureFiles.push_back(_zipDir.path() + "/" + info.fileName());
|
// Compress and copy
|
||||||
|
if (!compressFile(info.filePath(), _zipDir.path() + "/" + info.fileName())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
_totalSize += info.size();
|
_totalSize += info.size();
|
||||||
compressFile(info.canonicalFilePath(), _textureFiles.back());
|
if (!addPart(_zipDir.path() + "/" + info.fileName(),
|
||||||
|
QString("texture%1").arg(++_texturesCount))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (info.isDir()) {
|
} else if (info.isDir()) {
|
||||||
if (!addTextures(info)) {
|
if (!addTextures(info)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -153,7 +197,26 @@ bool FstReader::compressFile(const QString &inFileName, const QString &outFileNa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FstReader::addPart(const QString &path, const QString& name) {
|
||||||
|
QFile* file = new QFile(path);
|
||||||
|
if (!file->open(QIODevice::ReadOnly)) {
|
||||||
|
qDebug() << "[ERROR] Couldn't open " << file->fileName();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHttpPart part;
|
||||||
|
part.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
|
||||||
|
" name=\"" + name.toUtf8() + "\";"
|
||||||
|
" filename=\"" + QFileInfo(*file).fileName().toUtf8() + "\"");
|
||||||
|
part.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
|
||||||
|
part.setBodyDevice(file);
|
||||||
|
_dataMultiPart->append(part);
|
||||||
|
file->setParent(_dataMultiPart);
|
||||||
|
|
||||||
|
qDebug() << QFileInfo(*file).fileName().toUtf8();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,39 +10,31 @@
|
||||||
#ifndef __hifi__FstReader__
|
#ifndef __hifi__FstReader__
|
||||||
#define __hifi__FstReader__
|
#define __hifi__FstReader__
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QList>
|
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
|
class QHttpMultiPart;
|
||||||
static const QString nameField = "name";
|
|
||||||
static const QString filenameField = "filename";
|
|
||||||
static const QString texdirField = "texdir";
|
|
||||||
static const QString lodField = "lod";
|
|
||||||
|
|
||||||
static const int MAX_SIZE = 1024 * 1024; // 1 MB
|
|
||||||
|
|
||||||
class FstReader {
|
class FstReader {
|
||||||
public:
|
public:
|
||||||
FstReader();
|
FstReader();
|
||||||
|
~FstReader();
|
||||||
|
|
||||||
bool zip();
|
bool zip();
|
||||||
bool send();
|
bool send();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTemporaryDir _zipDir;
|
QTemporaryDir _zipDir;
|
||||||
|
int _lodCount;
|
||||||
QString _modelName;
|
int _texturesCount;
|
||||||
QString _fstFile;
|
|
||||||
QString _fbxFile;
|
|
||||||
QStringList _lodFiles;
|
|
||||||
QStringList _textureFiles;
|
|
||||||
|
|
||||||
int _totalSize;
|
int _totalSize;
|
||||||
|
bool _readyToSend;
|
||||||
|
|
||||||
|
QHttpMultiPart* _dataMultiPart;
|
||||||
|
|
||||||
|
|
||||||
bool addTextures(QFileInfo& texdir);
|
bool addTextures(const QFileInfo& texdir);
|
||||||
bool compressFile(const QString& inFileName, const QString& outFileName);
|
bool compressFile(const QString& inFileName, const QString& outFileName);
|
||||||
|
bool addPart(const QString& path, const QString& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__FstReader__) */
|
#endif /* defined(__hifi__FstReader__) */
|
||||||
|
|
Loading…
Reference in a new issue