Browse Source

Added overwrite flag for file upload

Moved md5 hash check into ctkXnatSession
Andreas Fetzer 10 years ago
parent
commit
448bd4eade

+ 17 - 53
Libs/XNAT/Core/ctkXnatFile.cpp

@@ -151,9 +151,13 @@ void ctkXnatFile::downloadImpl(const QString& filename)
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-void ctkXnatFile::saveImpl()
+void ctkXnatFile::saveImpl(bool overwrite)
 {
 {
   Q_D(ctkXnatFile);
   Q_D(ctkXnatFile);
+
+  QMap<QString, QString> urlParams;
+  urlParams["xsi:type"] = this->schemaType();
+  urlParams["inbody"] = "true";
   QString query = this->resourceUri();
   QString query = this->resourceUri();
   QString filename = this->localFilePath();
   QString filename = this->localFilePath();
 
 
@@ -180,64 +184,24 @@ void ctkXnatFile::saveImpl()
         itProperties.key() == FILE_CONTENT)
         itProperties.key() == FILE_CONTENT)
       continue;
       continue;
 
 
+    urlParams[itProperties.key()] = itProperties.value();
     query.append(QString("&%1=%2").arg(itProperties.key(), itProperties.value()));
     query.append(QString("&%1=%2").arg(itProperties.key(), itProperties.value()));
   }
   }
-  query.append(QString("&%1=%2").arg("format", this->fileFormat()));
-  query.append(QString("&%1=%2").arg("content", this->fileContent()));
-  query.append(QString("&%1=%2").arg("tags", this->fileTags()));
+  if (!this->fileFormat().isNull())
+    urlParams["format"] = this->fileFormat();
+  if (!this->fileContent().isNull())
+    urlParams["content"] = this->fileContent();
+  if (!this->fileContent().isNull())
+    urlParams["tags"] = this->fileTags();
 
 
-  // TODO May be flag for setting overwrite and not doing this automatically
-  if (this->exists())
-    query.append(QString("&%1=%2").arg("overwrite", true));
+  if (this->exists() && overwrite)
+    urlParams["overwrite"] = "true";
 
 
   // Flag needed for file upload
   // Flag needed for file upload
   query.append(QString("&%1=%2").arg("inbody", "true"));
   query.append(QString("&%1=%2").arg("inbody", "true"));
 
 
-  this->session()->upload(filename, query);
-
-  // Validating the file upload by requesting the catalog XML
-  // of the parent resource. Unfortunately for XNAT versions <= 1.6.4
-  // this is the only way to get the file's MD5 hash form the server.
-  QString md5Query = this->parent()->resourceUri();
-  QUuid md5ID = this->session()->httpGet(md5Query);
-  QList<QVariantMap> result = this->session()->httpSync(md5ID);
-
-  QString md5ChecksumRemote ("0");
-  // Newly added files are usually at the end of the catalog
-  // and hence at the end of the result list. So iterating backwards
-  // is for performance reasons.
-  QList<QVariantMap>::const_iterator it = result.constEnd()-1;
-  while (it != result.constBegin()-1)
-  {
-    QVariantMap::const_iterator it2 = (*it).find(this->name());
-    if (it2 != (*it).constEnd())
-    {
-      md5ChecksumRemote = it2.value().toString();
-      break;
-    }
-    --it;
-  }
-
-  if (file.open(QFile::ReadOnly) && md5ChecksumRemote != "0")
-  {
-    QCryptographicHash hash(QCryptographicHash::Md5);
-    // TODO Do this in case of Qt5
-    //if (hash.addData(&file))
-    hash.addData(file.readAll());
-    QString md5ChecksumLocal(hash.result().toHex());
-    // Retrieving the md5 checksum on the server and comparing
-    // it with the local file md5 sum
-    if (md5ChecksumLocal != md5ChecksumRemote)
-    {
-      // Remove corrupted file from server
-      this->erase();
-      throw ctkXnatException("Upload failed! An error occurred during file upload.");
-    }
-  }
-  else
-  {
-    qWarning()<<"Could not validate file upload!";
-  }
-  // End file validation
+  this->session()->upload(this, urlParams);
 
 
+//  d->setIsModified();
+//  this->parent()->fetch();
 }
 }

+ 1 - 2
Libs/XNAT/Core/ctkXnatFile.h

@@ -75,9 +75,8 @@ private:
   /**
   /**
     * @brief Uploads the file to the server
     * @brief Uploads the file to the server
     * Before calling save() the localFilePath has to be set
     * Before calling save() the localFilePath has to be set
-    * @throws ctkXnatException it the specified file does not exists
     */
     */
-  virtual void saveImpl();
+  virtual void saveImpl(bool overwrite);
 
 
   Q_DECLARE_PRIVATE(ctkXnatFile)
   Q_DECLARE_PRIVATE(ctkXnatFile)
 };
 };

+ 3 - 3
Libs/XNAT/Core/ctkXnatObject.cpp

@@ -314,10 +314,10 @@ void ctkXnatObject::download(const QString& filename)
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-void ctkXnatObject::save()
+void ctkXnatObject::save(bool overwrite)
 {
 {
   Q_D(ctkXnatObject);
   Q_D(ctkXnatObject);
-  this->saveImpl();
+  this->saveImpl(overwrite);
   d->modified = false;
   d->modified = false;
 }
 }
 
 
@@ -369,7 +369,7 @@ bool ctkXnatObject::exists() const
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-void ctkXnatObject::saveImpl()
+void ctkXnatObject::saveImpl(bool /*overwrite*/)
 {
 {
   Q_D(ctkXnatObject);
   Q_D(ctkXnatObject);
   QString query = this->resourceUri();
   QString query = this->resourceUri();

+ 6 - 2
Libs/XNAT/Core/ctkXnatObject.h

@@ -123,7 +123,9 @@ public:
   bool exists() const;
   bool exists() const;
 
 
   /// Creates the object on the XNAT server and sets the new ID.
   /// Creates the object on the XNAT server and sets the new ID.
-  void save();
+  /// @param overwrite, if true and the object already exists on the server
+  ///                   it will be overwritten by the changes
+  void save(bool overwrite = true);
 
 
   /// Deletes the object on the XNAT server and removes it from its parent.
   /// Deletes the object on the XNAT server and removes it from its parent.
   void erase();
   void erase();
@@ -187,7 +189,9 @@ private:
 
 
   /// The implementation of the upload mechanism, called by the save() function.
   /// The implementation of the upload mechanism, called by the save() function.
   /// Subclasses of ctkXnatObject can overwrite this function if needed
   /// Subclasses of ctkXnatObject can overwrite this function if needed
-  virtual void saveImpl();
+  /// @param overwrite, if true and the object already exists on the server
+  ///                   it will be overwritten by the changes
+  virtual void saveImpl(bool overwrite = true);
 
 
   Q_DECLARE_PRIVATE(ctkXnatObject)
   Q_DECLARE_PRIVATE(ctkXnatObject)
 };
 };

+ 1 - 1
Libs/XNAT/Core/ctkXnatResource.cpp

@@ -167,7 +167,7 @@ void ctkXnatResource::downloadImpl(const QString& filename)
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-void ctkXnatResource::saveImpl()
+void ctkXnatResource::saveImpl(bool /*overwrite*/)
 {
 {
   QString query = this->resourceUri();
   QString query = this->resourceUri();
 
 

+ 1 - 1
Libs/XNAT/Core/ctkXnatResource.h

@@ -67,7 +67,7 @@ public:
 
 
   void reset();
   void reset();
 
 
-  void saveImpl();
+  void saveImpl(bool overwrite);
 
 
   static const QString ID;
   static const QString ID;
   static const QString TAGS;
   static const QString TAGS;

+ 1 - 1
Libs/XNAT/Core/ctkXnatResourceFolder.cpp

@@ -101,7 +101,7 @@ void ctkXnatResourceFolder::downloadImpl(const QString& filename)
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-void ctkXnatResourceFolder::saveImpl()
+void ctkXnatResourceFolder::saveImpl(bool /*overwrite*/)
 {
 {
   // Not implemented since a resource folder is automatically created when
   // Not implemented since a resource folder is automatically created when
   // a resource is uploaded
   // a resource is uploaded

+ 1 - 1
Libs/XNAT/Core/ctkXnatResourceFolder.h

@@ -49,7 +49,7 @@ private:
   friend class qRestResult;
   friend class qRestResult;
   virtual void fetchImpl();
   virtual void fetchImpl();
   virtual void downloadImpl(const QString&);
   virtual void downloadImpl(const QString&);
-  virtual void saveImpl();
+  virtual void saveImpl(bool overwrite);
 
 
   Q_DECLARE_PRIVATE(ctkXnatResourceFolder)
   Q_DECLARE_PRIVATE(ctkXnatResourceFolder)
 };
 };

+ 52 - 4
Libs/XNAT/Core/ctkXnatSession.cpp

@@ -35,6 +35,7 @@
 #include "ctkXnatScan.h"
 #include "ctkXnatScan.h"
 #include "ctkXnatSubject.h"
 #include "ctkXnatSubject.h"
 
 
+#include <QCryptographicHash>
 #include <QDateTime>
 #include <QDateTime>
 #include <QDebug>
 #include <QDebug>
 #include <QDir>
 #include <QDir>
@@ -615,14 +616,61 @@ void ctkXnatSession::download(const QString& fileName,
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
-void ctkXnatSession::upload(const QString &fileName,
-                            const QString &resource,
+void ctkXnatSession::upload(ctkXnatFile *file,
                             const UrlParameters &parameters,
                             const UrlParameters &parameters,
-                            const HttpRawHeaders &rawHeaders)
+                            const HttpRawHeaders &/*rawHeaders*/)
 {
 {
   Q_D(ctkXnatSession);
   Q_D(ctkXnatSession);
-  QUuid queryId = d->xnat->upload(fileName, resource, parameters);
+  QUuid queryId = d->xnat->upload(file->localFilePath(), file->resourceUri(), parameters);
   d->xnat->sync(queryId);
   d->xnat->sync(queryId);
+
+  // TODO this into session!!!
+  // Validating the file upload by requesting the catalog XML
+  // of the parent resource. Unfortunately for XNAT versions <= 1.6.4
+  // this is the only way to get the file's MD5 hash form the server.
+  QString md5Query = file->parent()->resourceUri();
+  QUuid md5ID = this->httpGet(md5Query);
+  QList<QVariantMap> result = this->httpSync(md5ID);
+
+  QString md5ChecksumRemote ("0");
+  // Newly added files are usually at the end of the catalog
+  // and hence at the end of the result list. So iterating backwards
+  // is for performance reasons.
+  QList<QVariantMap>::const_iterator it = result.constEnd()-1;
+  while (it != result.constBegin()-1)
+  {
+    QVariantMap::const_iterator it2 = (*it).find(file->name());
+    if (it2 != (*it).constEnd())
+    {
+      md5ChecksumRemote = it2.value().toString();
+      break;
+    }
+    --it;
+  }
+
+  QFile localFile(file->localFilePath());
+  if (localFile.open(QFile::ReadOnly) && md5ChecksumRemote != "0")
+  {
+    QCryptographicHash hash(QCryptographicHash::Md5);
+    // TODO Do this in case of Qt5
+    //if (hash.addData(&file))
+    hash.addData(localFile.readAll());
+    QString md5ChecksumLocal(hash.result().toHex());
+    // Retrieving the md5 checksum on the server and comparing
+    // it with the local file md5 sum
+    if (md5ChecksumLocal != md5ChecksumRemote)
+    {
+      // Remove corrupted file from server
+      file->erase();
+      // TODO qError! Exception im Pythonwrapping nicht auswertbar?
+      throw ctkXnatException("Upload failed! An error occurred during file upload.");
+    }
+  }
+  else
+  {
+    qWarning()<<"Could not validate file upload! Remote MD5: "<<md5ChecksumRemote;
+  }
+  // End file validation
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------

+ 1 - 2
Libs/XNAT/Core/ctkXnatSession.h

@@ -241,8 +241,7 @@ public:
   /// \a rawHeaders can be used to set the raw headers of the request to send.
   /// \a rawHeaders can be used to set the raw headers of the request to send.
   /// These headers will be set additionally to those defined by the
   /// These headers will be set additionally to those defined by the
   /// \a defaultRawHeaders property.
   /// \a defaultRawHeaders property.
-  void upload(const QString& fileName,
-    const QString& resource,
+  void upload(ctkXnatFile *,
     const UrlParameters& parameters = UrlParameters(),
     const UrlParameters& parameters = UrlParameters(),
     const HttpRawHeaders& rawHeaders = HttpRawHeaders());
     const HttpRawHeaders& rawHeaders = HttpRawHeaders());