# HG changeset patch # User Sebastien Jodogne # Date 1607429860 -3600 # Node ID 886bc367aeb29599ed64ed0bf1142c599357c5b5 # Parent 18c94a82f3d4f655d716d40f7e1c1006eedba232 "/instances" can be used to import ZIP archives provided in the POST body diff -r 18c94a82f3d4 -r 886bc367aeb2 NEWS --- a/NEWS Tue Dec 08 12:55:32 2020 +0100 +++ b/NEWS Tue Dec 08 13:17:40 2020 +0100 @@ -2,6 +2,12 @@ =============================== +REST API +-------- + +* "/instances" can be used to import ZIP archives provided in the POST body + + Version 1.8.1 (2020-12-07) ========================== diff -r 18c94a82f3d4 -r 886bc367aeb2 OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Tue Dec 08 12:55:32 2020 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Tue Dec 08 13:17:40 2020 +0100 @@ -35,6 +35,7 @@ #include "OrthancRestApi.h" #include "../../../OrthancFramework/Sources/Compression/GzipCompressor.h" +#include "../../../OrthancFramework/Sources/Compression/ZipReader.h" #include "../../../OrthancFramework/Sources/Logging.h" #include "../../../OrthancFramework/Sources/MetricsRegistry.h" #include "../../../OrthancFramework/Sources/SerializationToolbox.h" @@ -61,18 +62,26 @@ } + static void SetupResourceAnswer(Json::Value& result, + DicomInstanceToStore& instance, + StoreStatus status, + const std::string& instanceId) + { + SetupResourceAnswer(result, instanceId, ResourceType_Instance, status); + + result["ParentPatient"] = instance.GetHasher().HashPatient(); + result["ParentStudy"] = instance.GetHasher().HashStudy(); + result["ParentSeries"] = instance.GetHasher().HashSeries(); + } + + void OrthancRestApi::AnswerStoredInstance(RestApiPostCall& call, DicomInstanceToStore& instance, StoreStatus status, const std::string& instanceId) const { Json::Value result; - SetupResourceAnswer(result, instanceId, ResourceType_Instance, status); - - result["ParentPatient"] = instance.GetHasher().HashPatient(); - result["ParentStudy"] = instance.GetHasher().HashStudy(); - result["ParentSeries"] = instance.GetHasher().HashSeries(); - + SetupResourceAnswer(result, instance, status, instanceId); call.GetOutput().AnswerJson(result); } @@ -121,28 +130,75 @@ "Received an empty DICOM file"); } - // The lifetime of "dicom" must be longer than "toStore", as the - // latter can possibly store a reference to the former (*) - std::string dicom; + if (ZipReader::IsZipMemoryBuffer(call.GetBodyData(), call.GetBodySize())) + { + // New in Orthanc 1.9.0 + std::unique_ptr reader(ZipReader::CreateFromMemory(call.GetBodyData(), call.GetBodySize())); + + Json::Value answer = Json::arrayValue; + + std::string filename, content; + while (reader->ReadNextFile(filename, content)) + { + if (!content.empty()) + { + LOG(INFO) << "Uploading DICOM file from ZIP archive: " << filename; + + DicomInstanceToStore toStore; + toStore.SetOrigin(DicomInstanceOrigin::FromRest(call)); + toStore.SetBuffer(content.c_str(), content.size()); + + std::string publicId; - DicomInstanceToStore toStore; - toStore.SetOrigin(DicomInstanceOrigin::FromRest(call)); + try + { + StoreStatus status = context.Store(publicId, toStore, StoreInstanceMode_Default); - if (boost::iequals(call.GetHttpHeader("content-encoding", ""), "gzip")) - { - GzipCompressor compressor; - compressor.Uncompress(dicom, call.GetBodyData(), call.GetBodySize()); - toStore.SetBuffer(dicom.c_str(), dicom.size()); // (*) + Json::Value info; + SetupResourceAnswer(info, toStore, status, publicId); + answer.append(info); + } + catch (OrthancException& e) + { + if (e.GetErrorCode() == ErrorCode_BadFileFormat) + { + LOG(ERROR) << "Cannot import non-DICOM file from ZIP archive: " << filename; + } + else + { + throw; + } + } + } + } + + call.GetOutput().AnswerJson(answer); } else { - toStore.SetBuffer(call.GetBodyData(), call.GetBodySize()); - } + // The lifetime of "dicom" must be longer than "toStore", as the + // latter can possibly store a reference to the former (*) + std::string dicom; + + DicomInstanceToStore toStore; + toStore.SetOrigin(DicomInstanceOrigin::FromRest(call)); - std::string publicId; - StoreStatus status = context.Store(publicId, toStore, StoreInstanceMode_Default); + if (boost::iequals(call.GetHttpHeader("content-encoding", ""), "gzip")) + { + GzipCompressor compressor; + compressor.Uncompress(dicom, call.GetBodyData(), call.GetBodySize()); + toStore.SetBuffer(dicom.c_str(), dicom.size()); // (*) + } + else + { + toStore.SetBuffer(call.GetBodyData(), call.GetBodySize()); + } - OrthancRestApi::GetApi(call).AnswerStoredInstance(call, toStore, status, publicId); + std::string publicId; + StoreStatus status = context.Store(publicId, toStore, StoreInstanceMode_Default); + + OrthancRestApi::GetApi(call).AnswerStoredInstance(call, toStore, status, publicId); + } }