Use a random session id for a sequence of chunks

This commit is contained in:
Simon Walton 2018-11-16 15:56:39 -08:00
parent 5883035991
commit 2d2cc0eaca
3 changed files with 23 additions and 16 deletions

View file

@ -10,7 +10,7 @@ $(document).ready(function(){
function progressBarHTML(extraClass, label) { function progressBarHTML(extraClass, label) {
var html = "<div class='progress'>"; var html = "<div class='progress'>";
html += "<div class='" + extraClass + " progress-bar progress-bar-success progress-bar-striped active' role='progressbar' aria-valuemin='0' aria-valuemax='100'>"; html += "<div class='" + extraClass + " progress-bar progress-bar-success progress-bar-striped active' role='progressbar' aria-valuemin='0' aria-valuemax='100'>";
html += label + "<span class='ongoing-msg'></span></div></div>"; html += "<span class='ongoing-msg'></span></div></div>";
return html; return html;
} }
@ -24,10 +24,14 @@ $(document).ready(function(){
}); });
} }
function uploadNextChunk(file, offset) { function uploadNextChunk(file, offset, id) {
if (offset == undefined) { if (offset == undefined) {
offset = 0; offset = 0;
} }
if (id == undefined) {
// Identify this upload session
id = Math.round(Math.random() * 2147483647);
}
var fileSize = file.size; var fileSize = file.size;
var filename = file.name; var filename = file.name;
@ -45,6 +49,7 @@ $(document).ready(function(){
url: '/content/upload', url: '/content/upload',
type: 'POST', type: 'POST',
timeout: 30000, // 30 s timeout: 30000, // 30 s
headers: {"X-Session-Id": id},
cache: false, cache: false,
processData: false, processData: false,
contentType: false, contentType: false,
@ -64,7 +69,7 @@ $(document).ready(function(){
if (!isFinal) { if (!isFinal) {
ajaxObject.done(function (data, textStatus, jqXHR) ajaxObject.done(function (data, textStatus, jqXHR)
{ uploadNextChunk(file, offset + CHUNK_SIZE); }); { uploadNextChunk(file, offset + CHUNK_SIZE, id); });
} else { } else {
ajaxObject.done(function(data, textStatus, jqXHR) { ajaxObject.done(function(data, textStatus, jqXHR) {
isRestoring = true; isRestoring = true;
@ -210,7 +215,7 @@ $(document).ready(function(){
function updateProgressBars($progressBar, value) { function updateProgressBars($progressBar, value) {
$progressBar.attr('aria-valuenow', value).attr('style', 'width: ' + value + '%'); $progressBar.attr('aria-valuenow', value).attr('style', 'width: ' + value + '%');
$progressBar.find('.ongoing-msg').html(" " + Math.round(value) + "% Complete"); $progressBar.find('.ongoing-msg').html(" " + Math.round(value) + "%");
} }
function reloadBackupInformation() { function reloadBackupInformation() {

View file

@ -2519,18 +2519,21 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
} }
bool DomainServer::processPendingContent(HTTPConnection* connection, QString itemName, QString filename, QByteArray dataChunk) { bool DomainServer::processPendingContent(HTTPConnection* connection, QString itemName, QString filename, QByteArray dataChunk) {
static const QString UPLOAD_SESSION_KEY { "X-Session-Id" };
QByteArray sessionIdBytes = connection->requestHeader(UPLOAD_SESSION_KEY);
int sessionId = sessionIdBytes.toInt();
if (filename.endsWith(".zip", Qt::CaseInsensitive)) { if (filename.endsWith(".zip", Qt::CaseInsensitive)) {
static const QString TEMPORARY_CONTENT_FILEPATH { QDir::tempPath() + "/hifiUploadContent_XXXXXX.zip" }; static const QString TEMPORARY_CONTENT_FILEPATH { QDir::tempPath() + "/hifiUploadContent_XXXXXX.zip" };
const auto peerAddressHash = qHash(connection->socket()->peerAddress());
if (_pendingContentFiles.find(peerAddressHash) == _pendingContentFiles.end()) { if (_pendingContentFiles.find(sessionId) == _pendingContentFiles.end()) {
std::unique_ptr<QTemporaryFile> newTemp(new QTemporaryFile(TEMPORARY_CONTENT_FILEPATH)); std::unique_ptr<QTemporaryFile> newTemp(new QTemporaryFile(TEMPORARY_CONTENT_FILEPATH));
_pendingContentFiles[peerAddressHash] = std::move(newTemp); _pendingContentFiles[sessionId] = std::move(newTemp);
} }
QTemporaryFile& _pendingFileContent = *_pendingContentFiles[peerAddressHash]; QTemporaryFile& _pendingFileContent = *_pendingContentFiles[sessionId];
if (!_pendingFileContent.open()) { if (!_pendingFileContent.open()) {
_pendingContentFiles.erase(peerAddressHash); _pendingContentFiles.erase(sessionId);
connection->respond(HTTPConnection::StatusCode400); connection->respond(HTTPConnection::StatusCode400);
return false; return false;
} }
@ -2543,16 +2546,15 @@ bool DomainServer::processPendingContent(HTTPConnection* connection, QString ite
if (itemName == "restore-file-chunk-final" || itemName == "restore-file") { if (itemName == "restore-file-chunk-final" || itemName == "restore-file") {
auto deferred = makePromise("recoverFromUploadedBackup"); auto deferred = makePromise("recoverFromUploadedBackup");
deferred->then([this, peerAddressHash](QString error, QVariantMap result) { deferred->then([this, sessionId](QString error, QVariantMap result) {
_pendingContentFiles.erase(peerAddressHash); _pendingContentFiles.erase(sessionId);
}); });
_contentManager->recoverFromUploadedFile(deferred, _pendingFileContent.fileName()); _contentManager->recoverFromUploadedFile(deferred, _pendingFileContent.fileName());
} }
} else if (filename.endsWith(".json", Qt::CaseInsensitive) } else if (filename.endsWith(".json", Qt::CaseInsensitive)
|| filename.endsWith(".json.gz", Qt::CaseInsensitive)) { || filename.endsWith(".json.gz", Qt::CaseInsensitive)) {
auto peerAddressHash = qHash(connection->socket()->peerAddress()); QByteArray& _pendingUploadedContent = _pendingUploadedContents[sessionId];
QByteArray& _pendingUploadedContent = _pendingUploadedContents[peerAddressHash];
_pendingUploadedContent += dataChunk; _pendingUploadedContent += dataChunk;
connection->respond(HTTPConnection::StatusCode200); connection->respond(HTTPConnection::StatusCode200);
@ -2560,7 +2562,7 @@ bool DomainServer::processPendingContent(HTTPConnection* connection, QString ite
// invoke our method to hand the new octree file off to the octree server // invoke our method to hand the new octree file off to the octree server
QMetaObject::invokeMethod(this, "handleOctreeFileReplacement", QMetaObject::invokeMethod(this, "handleOctreeFileReplacement",
Qt::QueuedConnection, Q_ARG(QByteArray, _pendingUploadedContent)); Qt::QueuedConnection, Q_ARG(QByteArray, _pendingUploadedContent));
_pendingUploadedContents.erase(peerAddressHash); _pendingUploadedContents.erase(sessionId);
} }
} else { } else {
connection->respond(HTTPConnection::StatusCode400); connection->respond(HTTPConnection::StatusCode400);

View file

@ -284,8 +284,8 @@ private:
QHash<QUuid, QPointer<HTTPSConnection>> _pendingOAuthConnections; QHash<QUuid, QPointer<HTTPSConnection>> _pendingOAuthConnections;
std::unordered_map<uint, QByteArray> _pendingUploadedContents; std::unordered_map<int, QByteArray> _pendingUploadedContents;
std::unordered_map<uint, std::unique_ptr<QTemporaryFile>> _pendingContentFiles; std::unordered_map<int, std::unique_ptr<QTemporaryFile>> _pendingContentFiles;
QThread _assetClientThread; QThread _assetClientThread;
}; };