# HG changeset patch # User Sebastien Jodogne # Date 1354186655 -3600 # Node ID e5d5d4a9a32696ed36ef18c79b4f6ce737bd6ad3 # Parent c07170f3f4f7980559ac02e80350d863739d079b refactored upload of dicom through http diff -r c07170f3f4f7 -r e5d5d4a9a326 Core/RestApi/RestApi.h --- a/Core/RestApi/RestApi.h Thu Nov 29 11:25:29 2012 +0100 +++ b/Core/RestApi/RestApi.h Thu Nov 29 11:57:35 2012 +0100 @@ -107,7 +107,7 @@ const std::string* data_; public: - const std::string& GetData() + const std::string& GetPutBody() { return *data_; } @@ -121,7 +121,7 @@ const std::string* data_; public: - const std::string& GetData() + const std::string& GetPostBody() { return *data_; } diff -r c07170f3f4f7 -r e5d5d4a9a326 Core/RestApi/RestApiOutput.cpp --- a/Core/RestApi/RestApiOutput.cpp Thu Nov 29 11:25:29 2012 +0100 +++ b/Core/RestApi/RestApiOutput.cpp Thu Nov 29 11:57:35 2012 +0100 @@ -39,12 +39,12 @@ RestApiOutput::RestApiOutput(HttpOutput& output) : output_(output) { - existingResource_ = false; + alreadySent_ = false; } RestApiOutput::~RestApiOutput() { - if (!existingResource_) + if (!alreadySent_) { output_.SendHeader(Orthanc_HttpStatus_400_BadRequest); } @@ -52,7 +52,7 @@ void RestApiOutput::CheckStatus() { - if (existingResource_) + if (alreadySent_) { throw OrthancException(ErrorCode_BadSequenceOfCalls); } @@ -62,7 +62,7 @@ { CheckStatus(); sender.Send(output_); - existingResource_ = true; + alreadySent_ = true; } void RestApiOutput::AnswerJson(const Json::Value& value) @@ -71,7 +71,7 @@ Json::StyledWriter writer; std::string s = writer.write(value); output_.AnswerBufferWithContentType(s, "application/json"); - existingResource_ = true; + alreadySent_ = true; } void RestApiOutput::AnswerBuffer(const std::string& buffer, @@ -79,13 +79,25 @@ { CheckStatus(); output_.AnswerBufferWithContentType(buffer, contentType); - existingResource_ = true; + alreadySent_ = true; } void RestApiOutput::Redirect(const std::string& path) { CheckStatus(); output_.Redirect(path); - existingResource_ = true; + alreadySent_ = true; + } + + void RestApiOutput::SignalError(Orthanc_HttpStatus status) + { + if (status != Orthanc_HttpStatus_415_UnsupportedMediaType) + { + throw OrthancException("This HTTP status is not allowed in a REST API"); + } + + CheckStatus(); + output_.SendHeader(status); + alreadySent_ = true; } } diff -r c07170f3f4f7 -r e5d5d4a9a326 Core/RestApi/RestApiOutput.h --- a/Core/RestApi/RestApiOutput.h Thu Nov 29 11:25:29 2012 +0100 +++ b/Core/RestApi/RestApiOutput.h Thu Nov 29 11:57:35 2012 +0100 @@ -43,7 +43,7 @@ { private: HttpOutput& output_; - bool existingResource_; + bool alreadySent_; void CheckStatus(); @@ -59,6 +59,8 @@ void AnswerBuffer(const std::string& buffer, const std::string& contentType); + void SignalError(Orthanc_HttpStatus status); + void Redirect(const std::string& path); }; } diff -r c07170f3f4f7 -r e5d5d4a9a326 OrthancServer/OrthancRestApi.cpp --- a/OrthancServer/OrthancRestApi.cpp Thu Nov 29 11:25:29 2012 +0100 +++ b/OrthancServer/OrthancRestApi.cpp Thu Nov 29 11:57:35 2012 +0100 @@ -52,59 +52,6 @@ output.AnswerBufferWithContentType(s, "application/json"); } - bool OrthancRestApi::Store(Json::Value& result, - const std::string& postData) - { - // Prepare an input stream for the memory buffer - DcmInputBufferStream is; - if (postData.size() > 0) - { - is.setBuffer(&postData[0], postData.size()); - } - is.setEos(); - - //printf("[%d]\n", postData.size()); - - DcmFileFormat dicomFile; - if (dicomFile.read(is).good()) - { - DicomMap dicomSummary; - FromDcmtkBridge::Convert(dicomSummary, *dicomFile.getDataset()); - - DicomInstanceHasher hasher(dicomSummary); - - Json::Value dicomJson; - FromDcmtkBridge::ToJson(dicomJson, *dicomFile.getDataset()); - - StoreStatus status = StoreStatus_Failure; - if (postData.size() > 0) - { - status = index_.Store - (storage_, reinterpret_cast(&postData[0]), - postData.size(), dicomSummary, dicomJson, ""); - } - - result["ID"] = hasher.HashInstance(); - result["Path"] = "/instances/" + hasher.HashInstance(); - - switch (status) - { - case StoreStatus_Success: - result["Status"] = "Success"; - return true; - - case StoreStatus_AlreadyStored: - result["Status"] = "AlreadyStored"; - return true; - - default: - return false; - } - } - - return false; - } - void OrthancRestApi::ConnectToModality(DicomUserConnection& c, const std::string& name) { @@ -341,37 +288,6 @@ Json::Value result(Json::objectValue); - // List all the instances --------------------------------------------------- - - if (uri.size() == 1 && uri[0] == "instances") - { - if (method == "GET") - { - result = Json::Value(Json::arrayValue); - index_.GetAllUuids(result, ResourceType_Instance); - existingResource = true; - } - else if (method == "POST") - { - // Add a new instance to the storage - if (Store(result, postData)) - { - SendJson(output, result); - return; - } - else - { - output.SendHeader(Orthanc_HttpStatus_415_UnsupportedMediaType); - return; - } - } - else - { - output.SendMethodNotAllowedError("GET,POST"); - return; - } - } - // DICOM bridge ------------------------------------------------------------- if ((uri.size() == 2 || diff -r c07170f3f4f7 -r e5d5d4a9a326 OrthancServer/OrthancRestApi2.cpp --- a/OrthancServer/OrthancRestApi2.cpp Thu Nov 29 11:25:29 2012 +0100 +++ b/OrthancServer/OrthancRestApi2.cpp Thu Nov 29 11:57:35 2012 +0100 @@ -41,6 +41,7 @@ #include #include #include +#include #define RETRIEVE_CONTEXT(call) \ @@ -269,6 +270,58 @@ } + // Upload of DICOM files through HTTP --------------------------------------- + + static void UploadDicomFile(RestApi::PostCall& call) + { + RETRIEVE_CONTEXT(call); + + const std::string& postData = call.GetPostBody(); + + LOG(INFO) << "Receiving a DICOM file of " << postData.size() << " bytes through HTTP"; + + // Prepare an input stream for the memory buffer + DcmInputBufferStream is; + if (postData.size() > 0) + { + is.setBuffer(&postData[0], postData.size()); + } + is.setEos(); + + DcmFileFormat dicomFile; + if (!dicomFile.read(is).good()) + { + call.GetOutput().SignalError(Orthanc_HttpStatus_415_UnsupportedMediaType); + return; + } + + DicomMap dicomSummary; + FromDcmtkBridge::Convert(dicomSummary, *dicomFile.getDataset()); + + DicomInstanceHasher hasher(dicomSummary); + + Json::Value dicomJson; + FromDcmtkBridge::ToJson(dicomJson, *dicomFile.getDataset()); + + StoreStatus status = StoreStatus_Failure; + if (postData.size() > 0) + { + status = context.GetIndex().Store + (context.GetFileStorage(), reinterpret_cast(&postData[0]), + postData.size(), dicomSummary, dicomJson, ""); + } + + Json::Value result = Json::objectValue; + + if (status != StoreStatus_Failure) + { + result["ID"] = hasher.HashInstance(); + result["Path"] = GetBasePath(ResourceType_Instance, hasher.HashInstance()); + } + + result["Status"] = ToString(status); + call.GetOutput().AnswerJson(result); + } // DICOM bridge ------------------------------------------------------------- @@ -305,6 +358,7 @@ Register("/changes", GetChanges); Register("/modalities", ListModalities); + Register("/instances", UploadDicomFile); Register("/instances", ListResources); Register("/patients", ListResources); Register("/series", ListResources); diff -r c07170f3f4f7 -r e5d5d4a9a326 OrthancServer/ServerEnumerations.cpp --- a/OrthancServer/ServerEnumerations.cpp Thu Nov 29 11:25:29 2012 +0100 +++ b/OrthancServer/ServerEnumerations.cpp Thu Nov 29 11:57:35 2012 +0100 @@ -99,6 +99,25 @@ } } + const char* ToString(StoreStatus status) + { + switch (status) + { + case StoreStatus_Success: + return "Success"; + + case StoreStatus_AlreadyStored: + return "AlreadyStored"; + + case StoreStatus_Failure: + return "Failure"; + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + const char* ToString(ChangeType type) { switch (type) diff -r c07170f3f4f7 -r e5d5d4a9a326 OrthancServer/ServerEnumerations.h --- a/OrthancServer/ServerEnumerations.h Thu Nov 29 11:25:29 2012 +0100 +++ b/OrthancServer/ServerEnumerations.h Thu Nov 29 11:57:35 2012 +0100 @@ -99,5 +99,7 @@ const char* ToString(SeriesStatus status); + const char* ToString(StoreStatus status); + const char* ToString(ChangeType type); }