comparison OrthancServer/OrthancRestApi.cpp @ 646:fb49bf72ac2d

author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 30 Oct 2013 08:58:45 +0100
parents 60d90e48e809
children bcf5c9a767a9
comparison
equal deleted inserted replaced
645:75af92b18e23 646:fb49bf72ac2d
44 #include <dcmtk/dcmdata/dcistrmb.h> 44 #include <dcmtk/dcmdata/dcistrmb.h>
45 #include <dcmtk/dcmdata/dcfilefo.h> 45 #include <dcmtk/dcmdata/dcfilefo.h>
46 #include <boost/lexical_cast.hpp> 46 #include <boost/lexical_cast.hpp>
47 #include <glog/logging.h> 47 #include <glog/logging.h>
48 48
49 static const uint64_t MEGA_BYTES = 1024 * 1024;
50 static const uint64_t GIGA_BYTES = 1024 * 1024 * 1024;
51
49 52
50 #define RETRIEVE_CONTEXT(call) \ 53 #define RETRIEVE_CONTEXT(call) \
51 OrthancRestApi& contextApi = \ 54 OrthancRestApi& contextApi = \
52 dynamic_cast<OrthancRestApi&>(call.GetContext()); \ 55 dynamic_cast<OrthancRestApi&>(call.GetContext()); \
53 ServerContext& context = contextApi.GetContext() 56 ServerContext& context = contextApi.GetContext()
549 static bool ArchiveInternal(HierarchicalZipWriter& writer, 552 static bool ArchiveInternal(HierarchicalZipWriter& writer,
550 ServerContext& context, 553 ServerContext& context,
551 const std::string& publicId, 554 const std::string& publicId,
552 ResourceType resourceType, 555 ResourceType resourceType,
553 bool isFirstLevel) 556 bool isFirstLevel)
554 { 557 {
555 Json::Value resource; 558 Json::Value resource;
556 if (!context.GetIndex().LookupResource(resource, publicId, resourceType)) 559 if (!context.GetIndex().LookupResource(resource, publicId, resourceType))
557 { 560 {
558 return false; 561 return false;
559 } 562 }
560 563
561 if (isFirstLevel && 564 if (isFirstLevel &&
562 !CreateRootDirectoryInArchive(writer, context, resource, resourceType)) 565 !CreateRootDirectoryInArchive(writer, context, resource, resourceType))
563 { 566 {
564 return false; 567 return false;
610 613
611 template <enum ResourceType resourceType> 614 template <enum ResourceType resourceType>
612 static void GetArchive(RestApi::GetCall& call) 615 static void GetArchive(RestApi::GetCall& call)
613 { 616 {
614 RETRIEVE_CONTEXT(call); 617 RETRIEVE_CONTEXT(call);
618 std::string id = call.GetUriComponent("id", "");
619
620 /**
621 * Determine whether ZIP64 is required. Original ZIP format can
622 * store up to 2GB of data (some implementation supporting up to
623 * 4GB of data), and up to 65535 files.
624 * https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64
625 **/
626
627 uint64_t uncompressedSize;
628 uint64_t compressedSize;
629 unsigned int countStudies;
630 unsigned int countSeries;
631 unsigned int countInstances;
632 context.GetIndex().GetStatistics(compressedSize, uncompressedSize,
633 countStudies, countSeries, countInstances, id);
634 const bool isZip64 = (uncompressedSize >= 2 * GIGA_BYTES ||
635 countInstances >= 65535);
636
637 LOG(INFO) << "Creating a ZIP file with " << countInstances << " files of size "
638 << (uncompressedSize / MEGA_BYTES) << "MB using the "
639 << (isZip64 ? "ZIP64" : "ZIP32") << " file format";
615 640
616 // Create a RAII for the temporary file to manage the ZIP file 641 // Create a RAII for the temporary file to manage the ZIP file
617 Toolbox::TemporaryFile tmp; 642 Toolbox::TemporaryFile tmp;
618 std::string id = call.GetUriComponent("id", "");
619 643
620 { 644 {
621 // Create a ZIP writer 645 // Create a ZIP writer
622 HierarchicalZipWriter writer(tmp.GetPath().c_str()); 646 HierarchicalZipWriter writer(tmp.GetPath().c_str());
647 writer.SetZip64(isZip64);
623 648
624 // Store the requested resource into the ZIP 649 // Store the requested resource into the ZIP
625 if (!ArchiveInternal(writer, context, id, resourceType, true)) 650 if (!ArchiveInternal(writer, context, id, resourceType, true))
626 { 651 {
627 return; 652 return;