Mercurial > hg > orthanc
comparison OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp @ 4416:0b27841950d5
openapi about creation of zip/media archives
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 28 Dec 2020 16:49:17 +0100 |
parents | 05b8fd21089c |
children | a4518adede59 |
comparison
equal
deleted
inserted
replaced
4415:b50410d0e98c | 4416:0b27841950d5 |
---|---|
192 { | 192 { |
193 OrthancRestApi::SubmitGenericJob(output, context, job.release(), false, priority); | 193 OrthancRestApi::SubmitGenericJob(output, context, job.release(), false, priority); |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 | |
198 static void DocumentPostArguments(RestApiPostCall& call, | |
199 bool isMedia, | |
200 bool defaultExtended) | |
201 { | |
202 call.GetDocumentation() | |
203 .SetRequestField("Synchronous", RestApiCallDocumentation::Type_Boolean, | |
204 "If `true`, create the archive in synchronous mode, which means that the HTTP answer will directly " | |
205 "contain the ZIP file. This is the default, easy behavior, but it is *not* be desirable to archive " | |
206 "large amount of data, as it might lead to network timeouts.", false) | |
207 .SetRequestField("Asynchronous", RestApiCallDocumentation::Type_Boolean, | |
208 "If `true`, create the archive in asynchronous mode, which means that a job is submitted to create " | |
209 "the archive in background. Prefer this flavor wherever possible.", false) | |
210 .SetRequestField(KEY_TRANSCODE, RestApiCallDocumentation::Type_String, | |
211 "If present, the DICOM files in the archive will be transcoded to the provided " | |
212 "transfer syntax: https://book.orthanc-server.com/faq/transcoding.html", false) | |
213 .SetRequestField("Priority", RestApiCallDocumentation::Type_Number, | |
214 "In asynchronous mode, the priority of the job. The lower the value, the higher the priority.", false) | |
215 .AddAnswerType(MimeType_Zip, "In synchronous mode, the ZIP file containing the archive") | |
216 .AddAnswerType(MimeType_Json, "In asynchronous mode, information about the job that has been submitted to " | |
217 "generate the archive: https://book.orthanc-server.com/users/advanced-rest.html#jobs"); | |
218 | |
219 if (isMedia) | |
220 { | |
221 call.GetDocumentation().SetRequestField( | |
222 KEY_EXTENDED, RestApiCallDocumentation::Type_Boolean, "If `true`, will include additional " | |
223 "tags such as `SeriesDescription`, leading to a so-called *extended DICOMDIR*. Default value is " + | |
224 std::string(defaultExtended ? "`true`" : "`false`") + ".", false); | |
225 } | |
226 } | |
227 | |
197 | 228 |
198 template <bool IS_MEDIA, | 229 template <bool IS_MEDIA, |
199 bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > | 230 bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > |
200 static void CreateBatch(RestApiPostCall& call) | 231 static void CreateBatch(RestApiPostCall& call) |
201 { | 232 { |
233 if (call.IsDocumentation()) | |
234 { | |
235 DocumentPostArguments(call, IS_MEDIA, DEFAULT_IS_EXTENDED); | |
236 std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); | |
237 call.GetDocumentation() | |
238 .SetTag("System") | |
239 .SetSummary("Create " + m) | |
240 .SetDescription("Create a " + m + " containing the DICOM resources (patients, studies, series, or instances) " | |
241 "whose Orthanc identifiers are provided in the body") | |
242 .SetRequestField("Resources", RestApiCallDocumentation::Type_JsonListOfStrings, | |
243 "The list of Orthanc identifiers of interest.", false); | |
244 return; | |
245 } | |
246 | |
202 ServerContext& context = OrthancRestApi::GetContext(call); | 247 ServerContext& context = OrthancRestApi::GetContext(call); |
203 | 248 |
204 Json::Value body; | 249 Json::Value body; |
205 if (call.ParseJsonRequest(body)) | 250 if (call.ParseJsonRequest(body)) |
206 { | 251 { |
226 "Expected a list of resources to archive in the body"); | 271 "Expected a list of resources to archive in the body"); |
227 } | 272 } |
228 } | 273 } |
229 | 274 |
230 | 275 |
231 template <bool IS_MEDIA, | 276 template <bool IS_MEDIA> |
232 bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > | |
233 static void CreateSingleGet(RestApiGetCall& call) | 277 static void CreateSingleGet(RestApiGetCall& call) |
234 { | 278 { |
279 if (call.IsDocumentation()) | |
280 { | |
281 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | |
282 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | |
283 std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); | |
284 call.GetDocumentation() | |
285 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | |
286 .SetSummary("Create " + m) | |
287 .SetDescription("Synchronously create a " + m + " containing the DICOM " + r + | |
288 " whose Orthanc identifier is provided in the URL. This flavor is synchronous, " | |
289 "which might *not* be desirable to archive large amount of data, as it might " | |
290 "lead to network timeouts. Prefer the asynchronous version using `POST` method.") | |
291 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") | |
292 .SetHttpGetArgument("transcode", RestApiCallDocumentation::Type_String, | |
293 "If present, the DICOM files in the archive will be transcoded to the provided " | |
294 "transfer syntax: https://book.orthanc-server.com/faq/transcoding.html", false) | |
295 .AddAnswerType(MimeType_Zip, "ZIP file containing the archive"); | |
296 if (IS_MEDIA) | |
297 { | |
298 call.GetDocumentation().SetHttpGetArgument( | |
299 "extended", RestApiCallDocumentation::Type_String, | |
300 "If present, will include additional tags such as `SeriesDescription`, leading to a so-called *extended DICOMDIR*", false); | |
301 } | |
302 return; | |
303 } | |
304 | |
235 ServerContext& context = OrthancRestApi::GetContext(call); | 305 ServerContext& context = OrthancRestApi::GetContext(call); |
236 | 306 |
237 std::string id = call.GetUriComponent("id", ""); | 307 std::string id = call.GetUriComponent("id", ""); |
238 | 308 |
239 bool extended; | 309 bool extended; |
258 SubmitJob(call.GetOutput(), context, job, 0 /* priority */, | 328 SubmitJob(call.GetOutput(), context, job, 0 /* priority */, |
259 true /* synchronous */, id + ".zip"); | 329 true /* synchronous */, id + ".zip"); |
260 } | 330 } |
261 | 331 |
262 | 332 |
263 template <bool IS_MEDIA, | 333 template <bool IS_MEDIA> |
264 bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > | |
265 static void CreateSinglePost(RestApiPostCall& call) | 334 static void CreateSinglePost(RestApiPostCall& call) |
266 { | 335 { |
336 if (call.IsDocumentation()) | |
337 { | |
338 DocumentPostArguments(call, IS_MEDIA, false /* not extended by default */); | |
339 ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); | |
340 std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); | |
341 std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); | |
342 call.GetDocumentation() | |
343 .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) | |
344 .SetSummary("Create " + m) | |
345 .SetDescription("Create a " + m + " containing the DICOM " + r + | |
346 " whose Orthanc identifier is provided in the URL") | |
347 .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest"); | |
348 return; | |
349 } | |
350 | |
267 ServerContext& context = OrthancRestApi::GetContext(call); | 351 ServerContext& context = OrthancRestApi::GetContext(call); |
268 | 352 |
269 std::string id = call.GetUriComponent("id", ""); | 353 std::string id = call.GetUriComponent("id", ""); |
270 | 354 |
271 Json::Value body; | 355 Json::Value body; |
273 { | 357 { |
274 bool synchronous, extended, transcode; | 358 bool synchronous, extended, transcode; |
275 DicomTransferSyntax transferSyntax; | 359 DicomTransferSyntax transferSyntax; |
276 int priority; | 360 int priority; |
277 GetJobParameters(synchronous, extended, transcode, transferSyntax, | 361 GetJobParameters(synchronous, extended, transcode, transferSyntax, |
278 priority, body, DEFAULT_IS_EXTENDED); | 362 priority, body, false /* by default, not extented */); |
279 | 363 |
280 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); | 364 std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); |
281 job->AddResource(id); | 365 job->AddResource(id); |
282 | 366 |
283 if (transcode) | 367 if (transcode) |
294 } | 378 } |
295 | 379 |
296 | 380 |
297 void OrthancRestApi::RegisterArchive() | 381 void OrthancRestApi::RegisterArchive() |
298 { | 382 { |
299 Register("/patients/{id}/archive", | 383 Register("/patients/{id}/archive", CreateSingleGet<false /* ZIP */>); |
300 CreateSingleGet<false /* ZIP */, false /* extended makes no sense in ZIP */>); | 384 Register("/patients/{id}/archive", CreateSinglePost<false /* ZIP */>); |
301 Register("/studies/{id}/archive", | 385 Register("/patients/{id}/media", CreateSingleGet<true /* media */>); |
302 CreateSingleGet<false /* ZIP */, false /* extended makes no sense in ZIP */>); | 386 Register("/patients/{id}/media", CreateSinglePost<true /* media */>); |
303 Register("/series/{id}/archive", | 387 Register("/series/{id}/archive", CreateSingleGet<false /* ZIP */>); |
304 CreateSingleGet<false /* ZIP */, false /* extended makes no sense in ZIP */>); | 388 Register("/series/{id}/archive", CreateSinglePost<false /* ZIP */>); |
305 | 389 Register("/series/{id}/media", CreateSingleGet<true /* media */>); |
306 Register("/patients/{id}/archive", | 390 Register("/series/{id}/media", CreateSinglePost<true /* media */>); |
307 CreateSinglePost<false /* ZIP */, false /* extended makes no sense in ZIP */>); | 391 Register("/studies/{id}/archive", CreateSingleGet<false /* ZIP */>); |
308 Register("/studies/{id}/archive", | 392 Register("/studies/{id}/archive", CreateSinglePost<false /* ZIP */>); |
309 CreateSinglePost<false /* ZIP */, false /* extended makes no sense in ZIP */>); | 393 Register("/studies/{id}/media", CreateSingleGet<true /* media */>); |
310 Register("/series/{id}/archive", | 394 Register("/studies/{id}/media", CreateSinglePost<true /* media */>); |
311 CreateSinglePost<false /* ZIP */, false /* extended makes no sense in ZIP */>); | |
312 | |
313 Register("/patients/{id}/media", | |
314 CreateSingleGet<true /* media */, false /* not extended by default */>); | |
315 Register("/studies/{id}/media", | |
316 CreateSingleGet<true /* media */, false /* not extended by default */>); | |
317 Register("/series/{id}/media", | |
318 CreateSingleGet<true /* media */, false /* not extended by default */>); | |
319 | |
320 Register("/patients/{id}/media", | |
321 CreateSinglePost<true /* media */, false /* not extended by default */>); | |
322 Register("/studies/{id}/media", | |
323 CreateSinglePost<true /* media */, false /* not extended by default */>); | |
324 Register("/series/{id}/media", | |
325 CreateSinglePost<true /* media */, false /* not extended by default */>); | |
326 | 395 |
327 Register("/tools/create-archive", | 396 Register("/tools/create-archive", |
328 CreateBatch<false /* ZIP */, false /* extended makes no sense in ZIP */>); | 397 CreateBatch<false /* ZIP */, false /* extended makes no sense in ZIP */>); |
329 Register("/tools/create-media", | 398 Register("/tools/create-media", |
330 CreateBatch<true /* media */, false /* not extended by default */>); | 399 CreateBatch<true /* media */, false /* not extended by default */>); |