comparison OrthancServer/OrthancRestApi.cpp @ 250:f23318b11b39

creation of zip files
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 05 Dec 2012 12:29:10 +0100
parents 5694365ecb96
children 15fcd925b05b
comparison
equal deleted inserted replaced
249:5694365ecb96 250:f23318b11b39
294 call.GetOutput().Redirect("app/explorer.html"); 294 call.GetOutput().Redirect("app/explorer.html");
295 } 295 }
296 296
297 static void GetSystemInformation(RestApi::GetCall& call) 297 static void GetSystemInformation(RestApi::GetCall& call)
298 { 298 {
299 RETRIEVE_CONTEXT(call);
300 Json::Value result = Json::objectValue; 299 Json::Value result = Json::objectValue;
301 300
302 result["Version"] = ORTHANC_VERSION; 301 result["Version"] = ORTHANC_VERSION;
303 result["Name"] = GetGlobalStringParameter("Name", ""); 302 result["Name"] = GetGlobalStringParameter("Name", "");
304 303
351 } 350 }
352 351
353 352
354 // Download of ZIP files ---------------------------------------------------- 353 // Download of ZIP files ----------------------------------------------------
355 354
356 static void GetPatientArchive(RestApi::GetCall& call) 355
357 { 356 static std::string GetDirectoryNameInArchive(const Json::Value& resource,
358 RETRIEVE_CONTEXT(call); 357 ResourceType resourceType)
359 358 {
360 Json::Value patient; 359 switch (resourceType)
361 if (!context.GetIndex().LookupResource(patient, call.GetUriComponent("id", ""), ResourceType_Patient)) 360 {
362 { 361 case ResourceType_Patient:
363 return; 362 {
364 } 363 std::string p = resource["MainDicomTags"]["PatientID"].asString();
365 364 std::string n = resource["MainDicomTags"]["PatientName"].asString();
365 return p + " " + n;
366 }
367
368 case ResourceType_Study:
369 return resource["MainDicomTags"]["StudyDescription"].asString();
370
371 case ResourceType_Series:
372 return resource["MainDicomTags"]["SeriesDescription"].asString();
373
374 default:
375 throw OrthancException(ErrorCode_InternalError);
376 }
377 }
378
379 static bool CreateRootDirectoryInArchive(HierarchicalZipWriter& writer,
380 ServerContext& context,
381 const Json::Value& resource,
382 ResourceType resourceType)
383 {
384 if (resourceType == ResourceType_Patient)
385 {
386 return true;
387 }
388
389 ResourceType parentType = GetParentResourceType(resourceType);
390 Json::Value parent;
391
392 switch (resourceType)
393 {
394 case ResourceType_Study:
395 {
396 if (!context.GetIndex().LookupResource(parent, resource["ParentPatient"].asString(), parentType))
397 {
398 return false;
399 }
400
401 break;
402 }
403
404 case ResourceType_Series:
405 if (!context.GetIndex().LookupResource(parent, resource["ParentStudy"].asString(), parentType) ||
406 !CreateRootDirectoryInArchive(writer, context, parent, parentType))
407 {
408 return false;
409 }
410 break;
411
412 default:
413 throw OrthancException(ErrorCode_NotImplemented);
414 }
415
416 writer.OpenDirectory(GetDirectoryNameInArchive(parent, parentType).c_str());
417 return true;
418 }
419
420 static bool ArchiveInstance(HierarchicalZipWriter& writer,
421 ServerContext& context,
422 const std::string& instancePublicId)
423 {
424 Json::Value instance;
425 if (!context.GetIndex().LookupResource(instance, instancePublicId, ResourceType_Instance))
426 {
427 return false;
428 }
429
430 std::string filename = instance["MainDicomTags"]["SOPInstanceUID"].asString() + ".dcm";
431 writer.OpenFile(filename.c_str());
432
433 std::string dicom;
434 context.ReadFile(dicom, instancePublicId, FileContentType_Dicom);
435 writer.Write(dicom);
436
437 return true;
438 }
439
440 static bool ArchiveInternal(HierarchicalZipWriter& writer,
441 ServerContext& context,
442 const std::string& publicId,
443 ResourceType resourceType,
444 bool isFirstLevel)
445 {
446 Json::Value resource;
447 if (!context.GetIndex().LookupResource(resource, publicId, resourceType))
448 {
449 return false;
450 }
451
452 if (isFirstLevel &&
453 !CreateRootDirectoryInArchive(writer, context, resource, resourceType))
454 {
455 return false;
456 }
457
458 writer.OpenDirectory(GetDirectoryNameInArchive(resource, resourceType).c_str());
459
460 switch (resourceType)
461 {
462 case ResourceType_Patient:
463 for (size_t i = 0; i < resource["Studies"].size(); i++)
464 {
465 std::string studyId = resource["Studies"][i].asString();
466 if (!ArchiveInternal(writer, context, studyId, ResourceType_Study, false))
467 {
468 return false;
469 }
470 }
471 break;
472
473 case ResourceType_Study:
474 for (size_t i = 0; i < resource["Series"].size(); i++)
475 {
476 std::string seriesId = resource["Series"][i].asString();
477 if (!ArchiveInternal(writer, context, seriesId, ResourceType_Series, false))
478 {
479 return false;
480 }
481 }
482 break;
483
484 case ResourceType_Series:
485 for (size_t i = 0; i < resource["Instances"].size(); i++)
486 {
487 if (!ArchiveInstance(writer, context, resource["Instances"][i].asString()))
488 {
489 return false;
490 }
491 }
492 break;
493
494 default:
495 throw OrthancException(ErrorCode_InternalError);
496 }
497
498 writer.CloseDirectory();
499 return true;
500 }
501
502 template <enum ResourceType resourceType>
503 static void GetArchive(RestApi::GetCall& call)
504 {
505 RETRIEVE_CONTEXT(call);
506
507 // Create a RAII for the temporary file to manage the ZIP file
366 Toolbox::TemporaryFile tmp; 508 Toolbox::TemporaryFile tmp;
367 509 std::string id = call.GetUriComponent("id", "");
368 { 510
511 {
512 // Create a ZIP writer
369 HierarchicalZipWriter writer(tmp.GetPath().c_str()); 513 HierarchicalZipWriter writer(tmp.GetPath().c_str());
370 514
371 for (size_t i = 0; i < patient["Studies"].size(); i++) 515 // Store the requested resource into the ZIP
372 { 516 if (!ArchiveInternal(writer, context, id, resourceType, true))
373 Json::Value study; 517 {
374 if (context.GetIndex().LookupResource(study, patient["Studies"][i].asString(), ResourceType_Study)) 518 return;
375 { 519 }
376 writer.OpenDirectory(study["MainDicomTags"]["StudyDescription"].asString().c_str()); 520 }
377 521
378 for (size_t i = 0; i < study["Series"].size(); i++) 522 // Prepare the sending of the ZIP file
379 {
380 Json::Value series;
381 if (context.GetIndex().LookupResource(series, study["Series"][i].asString(), ResourceType_Series))
382 {
383 std::string m = series["MainDicomTags"]["Modality"].asString();
384 std::string s = series["MainDicomTags"]["SeriesDescription"].asString();
385 writer.OpenDirectory((m + " " + s).c_str());
386
387 for (size_t i = 0; i < series["Instances"].size(); i++)
388 {
389 Json::Value instance;
390 if (context.GetIndex().LookupResource(instance, series["Instances"][i].asString(), ResourceType_Instance))
391 {
392 writer.OpenFile(instance["MainDicomTags"]["SOPInstanceUID"].asString().c_str());
393 }
394 }
395
396 writer.CloseDirectory();
397 }
398 }
399
400 writer.CloseDirectory();
401 }
402 }
403 }
404
405 FilesystemHttpSender sender(tmp.GetPath().c_str()); 523 FilesystemHttpSender sender(tmp.GetPath().c_str());
524 sender.SetContentType("application/zip");
525 sender.SetDownloadFilename(id + ".zip");
526
527 // Send the ZIP
406 call.GetOutput().AnswerFile(sender); 528 call.GetOutput().AnswerFile(sender);
529
530 // The temporary file is automatically removed thanks to the RAII
407 } 531 }
408 532
409 533
410 // Changes API -------------------------------------------------------------- 534 // Changes API --------------------------------------------------------------
411 535
708 Register("/patients/{id}", GetSingleResource<ResourceType_Patient>); 832 Register("/patients/{id}", GetSingleResource<ResourceType_Patient>);
709 Register("/series/{id}", DeleteSingleResource<ResourceType_Series>); 833 Register("/series/{id}", DeleteSingleResource<ResourceType_Series>);
710 Register("/series/{id}", GetSingleResource<ResourceType_Series>); 834 Register("/series/{id}", GetSingleResource<ResourceType_Series>);
711 Register("/studies/{id}", DeleteSingleResource<ResourceType_Study>); 835 Register("/studies/{id}", DeleteSingleResource<ResourceType_Study>);
712 Register("/studies/{id}", GetSingleResource<ResourceType_Study>); 836 Register("/studies/{id}", GetSingleResource<ResourceType_Study>);
713 Register("/patients/{id}/archive", GetPatientArchive); 837
838 Register("/patients/{id}/archive", GetArchive<ResourceType_Patient>);
839 Register("/studies/{id}/archive", GetArchive<ResourceType_Study>);
840 Register("/series/{id}/archive", GetArchive<ResourceType_Series>);
714 841
715 Register("/instances/{id}/file", GetInstanceFile); 842 Register("/instances/{id}/file", GetInstanceFile);
716 Register("/instances/{id}/tags", GetInstanceTags<false>); 843 Register("/instances/{id}/tags", GetInstanceTags<false>);
717 Register("/instances/{id}/simplified-tags", GetInstanceTags<true>); 844 Register("/instances/{id}/simplified-tags", GetInstanceTags<true>);
718 Register("/instances/{id}/frames", ListFrames); 845 Register("/instances/{id}/frames", ListFrames);