Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp @ 4357:886bc367aeb2
"/instances" can be used to import ZIP archives provided in the POST body
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 08 Dec 2020 13:17:40 +0100 |
parents | a01b1c9cbef4 |
children | 79ef2b6d8e76 |
comparison
equal
deleted
inserted
replaced
4356:18c94a82f3d4 | 4357:886bc367aeb2 |
---|---|
33 | 33 |
34 #include "../PrecompiledHeadersServer.h" | 34 #include "../PrecompiledHeadersServer.h" |
35 #include "OrthancRestApi.h" | 35 #include "OrthancRestApi.h" |
36 | 36 |
37 #include "../../../OrthancFramework/Sources/Compression/GzipCompressor.h" | 37 #include "../../../OrthancFramework/Sources/Compression/GzipCompressor.h" |
38 #include "../../../OrthancFramework/Sources/Compression/ZipReader.h" | |
38 #include "../../../OrthancFramework/Sources/Logging.h" | 39 #include "../../../OrthancFramework/Sources/Logging.h" |
39 #include "../../../OrthancFramework/Sources/MetricsRegistry.h" | 40 #include "../../../OrthancFramework/Sources/MetricsRegistry.h" |
40 #include "../../../OrthancFramework/Sources/SerializationToolbox.h" | 41 #include "../../../OrthancFramework/Sources/SerializationToolbox.h" |
41 #include "../ServerContext.h" | 42 #include "../ServerContext.h" |
42 | 43 |
59 | 60 |
60 result["Status"] = EnumerationToString(status); | 61 result["Status"] = EnumerationToString(status); |
61 } | 62 } |
62 | 63 |
63 | 64 |
65 static void SetupResourceAnswer(Json::Value& result, | |
66 DicomInstanceToStore& instance, | |
67 StoreStatus status, | |
68 const std::string& instanceId) | |
69 { | |
70 SetupResourceAnswer(result, instanceId, ResourceType_Instance, status); | |
71 | |
72 result["ParentPatient"] = instance.GetHasher().HashPatient(); | |
73 result["ParentStudy"] = instance.GetHasher().HashStudy(); | |
74 result["ParentSeries"] = instance.GetHasher().HashSeries(); | |
75 } | |
76 | |
77 | |
64 void OrthancRestApi::AnswerStoredInstance(RestApiPostCall& call, | 78 void OrthancRestApi::AnswerStoredInstance(RestApiPostCall& call, |
65 DicomInstanceToStore& instance, | 79 DicomInstanceToStore& instance, |
66 StoreStatus status, | 80 StoreStatus status, |
67 const std::string& instanceId) const | 81 const std::string& instanceId) const |
68 { | 82 { |
69 Json::Value result; | 83 Json::Value result; |
70 SetupResourceAnswer(result, instanceId, ResourceType_Instance, status); | 84 SetupResourceAnswer(result, instance, status, instanceId); |
71 | |
72 result["ParentPatient"] = instance.GetHasher().HashPatient(); | |
73 result["ParentStudy"] = instance.GetHasher().HashStudy(); | |
74 result["ParentSeries"] = instance.GetHasher().HashSeries(); | |
75 | |
76 call.GetOutput().AnswerJson(result); | 85 call.GetOutput().AnswerJson(result); |
77 } | 86 } |
78 | 87 |
79 | 88 |
80 void OrthancRestApi::AnswerStoredResource(RestApiPostCall& call, | 89 void OrthancRestApi::AnswerStoredResource(RestApiPostCall& call, |
119 { | 128 { |
120 throw OrthancException(ErrorCode_BadFileFormat, | 129 throw OrthancException(ErrorCode_BadFileFormat, |
121 "Received an empty DICOM file"); | 130 "Received an empty DICOM file"); |
122 } | 131 } |
123 | 132 |
124 // The lifetime of "dicom" must be longer than "toStore", as the | 133 if (ZipReader::IsZipMemoryBuffer(call.GetBodyData(), call.GetBodySize())) |
125 // latter can possibly store a reference to the former (*) | 134 { |
126 std::string dicom; | 135 // New in Orthanc 1.9.0 |
127 | 136 std::unique_ptr<ZipReader> reader(ZipReader::CreateFromMemory(call.GetBodyData(), call.GetBodySize())); |
128 DicomInstanceToStore toStore; | 137 |
129 toStore.SetOrigin(DicomInstanceOrigin::FromRest(call)); | 138 Json::Value answer = Json::arrayValue; |
130 | 139 |
131 if (boost::iequals(call.GetHttpHeader("content-encoding", ""), "gzip")) | 140 std::string filename, content; |
132 { | 141 while (reader->ReadNextFile(filename, content)) |
133 GzipCompressor compressor; | 142 { |
134 compressor.Uncompress(dicom, call.GetBodyData(), call.GetBodySize()); | 143 if (!content.empty()) |
135 toStore.SetBuffer(dicom.c_str(), dicom.size()); // (*) | 144 { |
145 LOG(INFO) << "Uploading DICOM file from ZIP archive: " << filename; | |
146 | |
147 DicomInstanceToStore toStore; | |
148 toStore.SetOrigin(DicomInstanceOrigin::FromRest(call)); | |
149 toStore.SetBuffer(content.c_str(), content.size()); | |
150 | |
151 std::string publicId; | |
152 | |
153 try | |
154 { | |
155 StoreStatus status = context.Store(publicId, toStore, StoreInstanceMode_Default); | |
156 | |
157 Json::Value info; | |
158 SetupResourceAnswer(info, toStore, status, publicId); | |
159 answer.append(info); | |
160 } | |
161 catch (OrthancException& e) | |
162 { | |
163 if (e.GetErrorCode() == ErrorCode_BadFileFormat) | |
164 { | |
165 LOG(ERROR) << "Cannot import non-DICOM file from ZIP archive: " << filename; | |
166 } | |
167 else | |
168 { | |
169 throw; | |
170 } | |
171 } | |
172 } | |
173 } | |
174 | |
175 call.GetOutput().AnswerJson(answer); | |
136 } | 176 } |
137 else | 177 else |
138 { | 178 { |
139 toStore.SetBuffer(call.GetBodyData(), call.GetBodySize()); | 179 // The lifetime of "dicom" must be longer than "toStore", as the |
140 } | 180 // latter can possibly store a reference to the former (*) |
141 | 181 std::string dicom; |
142 std::string publicId; | 182 |
143 StoreStatus status = context.Store(publicId, toStore, StoreInstanceMode_Default); | 183 DicomInstanceToStore toStore; |
144 | 184 toStore.SetOrigin(DicomInstanceOrigin::FromRest(call)); |
145 OrthancRestApi::GetApi(call).AnswerStoredInstance(call, toStore, status, publicId); | 185 |
186 if (boost::iequals(call.GetHttpHeader("content-encoding", ""), "gzip")) | |
187 { | |
188 GzipCompressor compressor; | |
189 compressor.Uncompress(dicom, call.GetBodyData(), call.GetBodySize()); | |
190 toStore.SetBuffer(dicom.c_str(), dicom.size()); // (*) | |
191 } | |
192 else | |
193 { | |
194 toStore.SetBuffer(call.GetBodyData(), call.GetBodySize()); | |
195 } | |
196 | |
197 std::string publicId; | |
198 StoreStatus status = context.Store(publicId, toStore, StoreInstanceMode_Default); | |
199 | |
200 OrthancRestApi::GetApi(call).AnswerStoredInstance(call, toStore, status, publicId); | |
201 } | |
146 } | 202 } |
147 | 203 |
148 | 204 |
149 | 205 |
150 // Registration of the various REST handlers -------------------------------- | 206 // Registration of the various REST handlers -------------------------------- |