Mercurial > hg > orthanc
comparison OrthancServer/OrthancRestApi/OrthancRestArchive.cpp @ 2627:00b6a7f935fc jobs
refactoring of archive creation
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 25 May 2018 14:07:52 +0200 |
parents | 878b59270859 |
children | 7ba7d5806911 |
comparison
equal
deleted
inserted
replaced
2626:e09021ddc00d | 2627:00b6a7f935fc |
---|---|
56 // Download of ZIP files ---------------------------------------------------- | 56 // Download of ZIP files ---------------------------------------------------- |
57 | 57 |
58 static bool IsZip64Required(uint64_t uncompressedSize, | 58 static bool IsZip64Required(uint64_t uncompressedSize, |
59 unsigned int countInstances) | 59 unsigned int countInstances) |
60 { | 60 { |
61 static const uint64_t SAFETY_MARGIN = 64 * MEGA_BYTES; | 61 static const uint64_t SAFETY_MARGIN = 64 * MEGA_BYTES; // Should be large enough to hold DICOMDIR |
62 static const unsigned int FILES_MARGIN = 10; | |
62 | 63 |
63 /** | 64 /** |
64 * Determine whether ZIP64 is required. Original ZIP format can | 65 * Determine whether ZIP64 is required. Original ZIP format can |
65 * store up to 2GB of data (some implementation supporting up to | 66 * store up to 2GB of data (some implementation supporting up to |
66 * 4GB of data), and up to 65535 files. | 67 * 4GB of data), and up to 65535 files. |
67 * https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64 | 68 * https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64 |
68 **/ | 69 **/ |
69 | 70 |
70 const bool isZip64 = (uncompressedSize >= 2 * GIGA_BYTES - SAFETY_MARGIN || | 71 const bool isZip64 = (uncompressedSize >= 2 * GIGA_BYTES - SAFETY_MARGIN || |
71 countInstances >= 65535); | 72 countInstances >= 65535 - FILES_MARGIN); |
72 | 73 |
73 LOG(INFO) << "Creating a ZIP file with " << countInstances << " files of size " | 74 LOG(INFO) << "Creating a ZIP file with " << countInstances << " files of size " |
74 << (uncompressedSize / MEGA_BYTES) << "MB using the " | 75 << (uncompressedSize / MEGA_BYTES) << "MB using the " |
75 << (isZip64 ? "ZIP64" : "ZIP32") << " file format"; | 76 << (isZip64 ? "ZIP64" : "ZIP32") << " file format"; |
76 | 77 |
78 } | 79 } |
79 | 80 |
80 | 81 |
81 namespace | 82 namespace |
82 { | 83 { |
83 class ResourceIdentifiers | 84 class ResourceIdentifiers : public boost::noncopyable |
84 { | 85 { |
85 private: | 86 private: |
86 ResourceType level_; | 87 ResourceType level_; |
87 std::string patient_; | 88 std::string patient_; |
88 std::string study_; | 89 std::string study_; |
191 virtual void AddInstance(const std::string& instanceId, | 192 virtual void AddInstance(const std::string& instanceId, |
192 const FileInfo& dicom) = 0; | 193 const FileInfo& dicom) = 0; |
193 }; | 194 }; |
194 | 195 |
195 | 196 |
196 class ArchiveIndex | 197 class ArchiveIndex : public boost::noncopyable |
197 { | 198 { |
198 private: | 199 private: |
199 struct Instance | 200 struct Instance |
200 { | 201 { |
201 std::string id_; | 202 std::string id_; |
345 } | 346 } |
346 } | 347 } |
347 }; | 348 }; |
348 | 349 |
349 | 350 |
350 class StatisticsVisitor : public IArchiveVisitor | 351 |
352 class ArchiveCommands : public boost::noncopyable | |
351 { | 353 { |
352 private: | 354 private: |
353 uint64_t size_; | 355 enum Type |
354 unsigned int instances_; | 356 { |
357 Type_OpenDirectory, | |
358 Type_CloseDirectory, | |
359 Type_WriteInstance | |
360 }; | |
361 | |
362 class Command : public boost::noncopyable | |
363 { | |
364 private: | |
365 Type type_; | |
366 std::string filename_; | |
367 std::string instanceId_; | |
368 FileInfo info_; | |
369 | |
370 public: | |
371 explicit Command(Type type) : | |
372 type_(type) | |
373 { | |
374 assert(type_ == Type_CloseDirectory); | |
375 } | |
376 | |
377 Command(Type type, | |
378 const std::string& filename) : | |
379 type_(type), | |
380 filename_(filename) | |
381 { | |
382 assert(type_ == Type_OpenDirectory); | |
383 } | |
384 | |
385 Command(Type type, | |
386 const std::string& filename, | |
387 const std::string& instanceId, | |
388 const FileInfo& info) : | |
389 type_(type), | |
390 filename_(filename), | |
391 instanceId_(instanceId), | |
392 info_(info) | |
393 { | |
394 assert(type_ == Type_WriteInstance); | |
395 } | |
396 | |
397 void Apply(HierarchicalZipWriter& writer, | |
398 ServerContext& context, | |
399 DicomDirWriter* dicomDir, | |
400 const std::string& dicomDirFolder) const | |
401 { | |
402 switch (type_) | |
403 { | |
404 case Type_OpenDirectory: | |
405 writer.OpenDirectory(filename_.c_str()); | |
406 break; | |
407 | |
408 case Type_CloseDirectory: | |
409 writer.CloseDirectory(); | |
410 break; | |
411 | |
412 case Type_WriteInstance: | |
413 { | |
414 std::string content; | |
415 | |
416 try | |
417 { | |
418 context.ReadAttachment(content, info_); | |
419 } | |
420 catch (OrthancException& e) | |
421 { | |
422 LOG(WARNING) << "An instance was removed after the job was issued: " << instanceId_; | |
423 return; | |
424 } | |
425 | |
426 writer.OpenFile(filename_.c_str()); | |
427 writer.Write(content); | |
428 | |
429 if (dicomDir != NULL) | |
430 { | |
431 ParsedDicomFile parsed(content); | |
432 dicomDir->Add(dicomDirFolder, filename_, parsed); | |
433 } | |
434 | |
435 break; | |
436 } | |
437 | |
438 default: | |
439 throw OrthancException(ErrorCode_InternalError); | |
440 } | |
441 } | |
442 }; | |
443 | |
444 std::deque<Command*> commands_; | |
445 uint64_t uncompressedSize_; | |
446 unsigned int instancesCount_; | |
447 | |
448 | |
449 void ApplyInternal(HierarchicalZipWriter& writer, | |
450 ServerContext& context, | |
451 size_t index, | |
452 DicomDirWriter* dicomDir, | |
453 const std::string& dicomDirFolder) const | |
454 { | |
455 if (index >= commands_.size()) | |
456 { | |
457 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
458 } | |
459 | |
460 commands_[index]->Apply(writer, context, dicomDir, dicomDirFolder); | |
461 } | |
355 | 462 |
356 public: | 463 public: |
357 StatisticsVisitor() : size_(0), instances_(0) | 464 ArchiveCommands() : |
358 { | 465 uncompressedSize_(0), |
466 instancesCount_(0) | |
467 { | |
468 } | |
469 | |
470 ~ArchiveCommands() | |
471 { | |
472 for (std::deque<Command*>::iterator it = commands_.begin(); | |
473 it != commands_.end(); ++it) | |
474 { | |
475 assert(*it != NULL); | |
476 delete *it; | |
477 } | |
478 } | |
479 | |
480 size_t GetSize() const | |
481 { | |
482 return commands_.size(); | |
483 } | |
484 | |
485 unsigned int GetInstancesCount() const | |
486 { | |
487 return instancesCount_; | |
359 } | 488 } |
360 | 489 |
361 uint64_t GetUncompressedSize() const | 490 uint64_t GetUncompressedSize() const |
362 { | 491 { |
363 return size_; | 492 return uncompressedSize_; |
364 } | 493 } |
365 | 494 |
366 unsigned int GetInstancesCount() const | 495 void Apply(HierarchicalZipWriter& writer, |
367 { | 496 ServerContext& context, |
368 return instances_; | 497 size_t index, |
369 } | 498 DicomDirWriter& dicomDir, |
370 | 499 const std::string& dicomDirFolder) const |
371 virtual void Open(ResourceType level, | 500 { |
372 const std::string& publicId) | 501 ApplyInternal(writer, context, index, &dicomDir, dicomDirFolder); |
373 { | 502 } |
374 } | 503 |
375 | 504 void Apply(HierarchicalZipWriter& writer, |
376 virtual void Close() | 505 ServerContext& context, |
377 { | 506 size_t index) const |
378 } | 507 { |
379 | 508 ApplyInternal(writer, context, index, NULL, ""); |
380 virtual void AddInstance(const std::string& instanceId, | 509 } |
381 const FileInfo& dicom) | 510 |
382 { | 511 void AddOpenDirectory(const std::string& filename) |
383 instances_ ++; | 512 { |
384 size_ += dicom.GetUncompressedSize(); | 513 commands_.push_back(new Command(Type_OpenDirectory, filename)); |
514 } | |
515 | |
516 void AddCloseDirectory() | |
517 { | |
518 commands_.push_back(new Command(Type_CloseDirectory)); | |
519 } | |
520 | |
521 void AddWriteInstance(const std::string& filename, | |
522 const std::string& instanceId, | |
523 const FileInfo& info) | |
524 { | |
525 commands_.push_back(new Command(Type_WriteInstance, filename, instanceId, info)); | |
526 instancesCount_ ++; | |
527 uncompressedSize_ += info.GetUncompressedSize(); | |
528 } | |
529 | |
530 bool IsZip64() const | |
531 { | |
532 return IsZip64Required(GetUncompressedSize(), GetInstancesCount()); | |
385 } | 533 } |
386 }; | 534 }; |
387 | 535 |
388 | 536 |
389 class PrintVisitor : public IArchiveVisitor | 537 |
538 class ArchiveWriterVisitor : public IArchiveVisitor | |
390 { | 539 { |
391 private: | 540 private: |
392 std::ostream& out_; | 541 ArchiveCommands& commands_; |
393 std::string indent_; | 542 ServerContext& context_; |
394 | 543 char instanceFormat_[24]; |
395 public: | 544 unsigned int counter_; |
396 PrintVisitor(std::ostream& out) : out_(out) | |
397 { | |
398 } | |
399 | |
400 virtual void Open(ResourceType level, | |
401 const std::string& publicId) | |
402 { | |
403 switch (level) | |
404 { | |
405 case ResourceType_Patient: indent_ = ""; break; | |
406 case ResourceType_Study: indent_ = " "; break; | |
407 case ResourceType_Series: indent_ = " "; break; | |
408 default: | |
409 throw OrthancException(ErrorCode_InternalError); | |
410 } | |
411 | |
412 out_ << indent_ << publicId << std::endl; | |
413 } | |
414 | |
415 virtual void Close() | |
416 { | |
417 } | |
418 | |
419 virtual void AddInstance(const std::string& instanceId, | |
420 const FileInfo& dicom) | |
421 { | |
422 out_ << " " << instanceId << std::endl; | |
423 } | |
424 }; | |
425 | |
426 | |
427 class ArchiveWriterVisitor : public IArchiveVisitor | |
428 { | |
429 private: | |
430 HierarchicalZipWriter& writer_; | |
431 ServerContext& context_; | |
432 char instanceFormat_[24]; | |
433 unsigned int countInstances_; | |
434 | 545 |
435 static std::string GetTag(const DicomMap& tags, | 546 static std::string GetTag(const DicomMap& tags, |
436 const DicomTag& tag) | 547 const DicomTag& tag) |
437 { | 548 { |
438 const DicomValue* v = tags.TestAndGetValue(tag); | 549 const DicomValue* v = tags.TestAndGetValue(tag); |
447 return ""; | 558 return ""; |
448 } | 559 } |
449 } | 560 } |
450 | 561 |
451 public: | 562 public: |
452 ArchiveWriterVisitor(HierarchicalZipWriter& writer, | 563 ArchiveWriterVisitor(ArchiveCommands& commands, |
453 ServerContext& context) : | 564 ServerContext& context) : |
454 writer_(writer), | 565 commands_(commands), |
455 context_(context), | 566 context_(context), |
456 countInstances_(0) | 567 counter_(0) |
457 { | 568 { |
569 if (commands.GetSize() != 0) | |
570 { | |
571 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
572 } | |
573 | |
458 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%%08d.dcm"); | 574 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%%08d.dcm"); |
459 } | 575 } |
460 | 576 |
461 virtual void Open(ResourceType level, | 577 virtual void Open(ResourceType level, |
462 const std::string& publicId) | 578 const std::string& publicId) |
494 { | 610 { |
495 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%c%c%%06d.dcm", | 611 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%c%c%%06d.dcm", |
496 toupper(modality[0]), toupper(modality[1])); | 612 toupper(modality[0]), toupper(modality[1])); |
497 } | 613 } |
498 | 614 |
499 countInstances_ = 0; | 615 counter_ = 0; |
500 | 616 |
501 break; | 617 break; |
502 } | 618 } |
503 | 619 |
504 default: | 620 default: |
511 if (path.empty()) | 627 if (path.empty()) |
512 { | 628 { |
513 path = std::string("Unknown ") + EnumerationToString(level); | 629 path = std::string("Unknown ") + EnumerationToString(level); |
514 } | 630 } |
515 | 631 |
516 writer_.OpenDirectory(path.c_str()); | 632 commands_.AddOpenDirectory(path.c_str()); |
517 } | 633 } |
518 | 634 |
519 virtual void Close() | 635 virtual void Close() |
520 { | 636 { |
521 writer_.CloseDirectory(); | 637 commands_.AddCloseDirectory(); |
522 } | 638 } |
523 | 639 |
524 virtual void AddInstance(const std::string& instanceId, | 640 virtual void AddInstance(const std::string& instanceId, |
525 const FileInfo& dicom) | 641 const FileInfo& dicom) |
526 { | 642 { |
527 std::string content; | |
528 context_.ReadAttachment(content, dicom); | |
529 | |
530 char filename[24]; | 643 char filename[24]; |
531 snprintf(filename, sizeof(filename) - 1, instanceFormat_, countInstances_); | 644 snprintf(filename, sizeof(filename) - 1, instanceFormat_, counter_); |
532 countInstances_ ++; | 645 counter_ ++; |
533 | 646 |
534 writer_.OpenFile(filename); | 647 commands_.AddWriteInstance(filename, instanceId, dicom); |
535 writer_.Write(content); | |
536 } | 648 } |
537 | 649 |
538 static void Apply(RestApiOutput& output, | 650 static void Apply(RestApiOutput& output, |
539 ServerContext& context, | 651 ServerContext& context, |
540 ArchiveIndex& archive, | 652 ArchiveIndex& archive, |
541 const std::string& filename) | 653 const std::string& filename) |
542 { | 654 { |
543 archive.Expand(context.GetIndex()); | 655 ArchiveCommands commands; |
544 | 656 |
545 StatisticsVisitor stats; | 657 { |
546 archive.Apply(stats); | 658 ArchiveWriterVisitor visitor(commands, context); |
547 | 659 archive.Expand(context.GetIndex()); |
548 const bool isZip64 = IsZip64Required(stats.GetUncompressedSize(), stats.GetInstancesCount()); | 660 archive.Apply(visitor); |
661 } | |
549 | 662 |
550 // Create a RAII for the temporary file to manage the ZIP file | 663 // Create a RAII for the temporary file to manage the ZIP file |
551 TemporaryFile tmp; | 664 TemporaryFile tmp; |
552 | 665 |
553 { | 666 { |
554 // Create a ZIP writer | |
555 HierarchicalZipWriter writer(tmp.GetPath().c_str()); | 667 HierarchicalZipWriter writer(tmp.GetPath().c_str()); |
556 writer.SetZip64(isZip64); | 668 writer.SetZip64(commands.IsZip64()); |
557 | 669 |
558 ArchiveWriterVisitor v(writer, context); | 670 for (size_t i = 0; i < commands.GetSize(); i++) |
559 archive.Apply(v); | 671 { |
672 commands.Apply(writer, context, i); | |
673 } | |
560 } | 674 } |
561 | 675 |
562 // Prepare the sending of the ZIP file | 676 // Prepare the sending of the ZIP file |
563 FilesystemHttpSender sender(tmp.GetPath()); | 677 FilesystemHttpSender sender(tmp.GetPath()); |
564 sender.SetContentType("application/zip"); | 678 sender.SetContentType("application/zip"); |
573 | 687 |
574 | 688 |
575 class MediaWriterVisitor : public IArchiveVisitor | 689 class MediaWriterVisitor : public IArchiveVisitor |
576 { | 690 { |
577 private: | 691 private: |
578 HierarchicalZipWriter& writer_; | 692 ArchiveCommands& commands_; |
579 DicomDirWriter dicomDir_; | 693 ServerContext& context_; |
580 ServerContext& context_; | 694 unsigned int counter_; |
581 unsigned int countInstances_; | |
582 | 695 |
583 public: | 696 public: |
584 MediaWriterVisitor(HierarchicalZipWriter& writer, | 697 MediaWriterVisitor(ArchiveCommands& commands, |
585 ServerContext& context) : | 698 ServerContext& context) : |
586 writer_(writer), | 699 commands_(commands), |
587 context_(context), | 700 context_(context), |
588 countInstances_(0) | 701 counter_(0) |
589 { | 702 { |
590 } | |
591 | |
592 void EncodeDicomDir(std::string& result) | |
593 { | |
594 dicomDir_.Encode(result); | |
595 } | 703 } |
596 | 704 |
597 virtual void Open(ResourceType level, | 705 virtual void Open(ResourceType level, |
598 const std::string& publicId) | 706 const std::string& publicId) |
599 { | 707 { |
607 const FileInfo& dicom) | 715 const FileInfo& dicom) |
608 { | 716 { |
609 // "DICOM restricts the filenames on DICOM media to 8 | 717 // "DICOM restricts the filenames on DICOM media to 8 |
610 // characters (some systems wrongly use 8.3, but this does not | 718 // characters (some systems wrongly use 8.3, but this does not |
611 // conform to the standard)." | 719 // conform to the standard)." |
612 std::string filename = "IM" + boost::lexical_cast<std::string>(countInstances_); | 720 std::string filename = "IM" + boost::lexical_cast<std::string>(counter_); |
613 writer_.OpenFile(filename.c_str()); | 721 commands_.AddWriteInstance(filename, instanceId, dicom); |
614 | 722 |
615 std::string content; | 723 counter_ ++; |
616 context_.ReadAttachment(content, dicom); | |
617 writer_.Write(content); | |
618 | |
619 ParsedDicomFile parsed(content); | |
620 dicomDir_.Add("IMAGES", filename, parsed); | |
621 | |
622 countInstances_ ++; | |
623 } | 724 } |
624 | 725 |
625 static void Apply(RestApiOutput& output, | 726 static void Apply(RestApiOutput& output, |
626 ServerContext& context, | 727 ServerContext& context, |
627 ArchiveIndex& archive, | 728 ArchiveIndex& archive, |
628 const std::string& filename, | 729 const std::string& filename, |
629 bool enableExtendedSopClass) | 730 bool enableExtendedSopClass) |
630 { | 731 { |
631 archive.Expand(context.GetIndex()); | 732 static const char* IMAGES_FOLDER = "IMAGES"; |
632 | 733 |
633 StatisticsVisitor stats; | 734 ArchiveCommands commands; |
634 archive.Apply(stats); | 735 |
635 | 736 { |
636 const bool isZip64 = IsZip64Required(stats.GetUncompressedSize(), stats.GetInstancesCount()); | 737 MediaWriterVisitor visitor(commands, context); |
738 archive.Expand(context.GetIndex()); | |
739 | |
740 commands.AddOpenDirectory(IMAGES_FOLDER); | |
741 archive.Apply(visitor); | |
742 commands.AddCloseDirectory(); | |
743 } | |
637 | 744 |
638 // Create a RAII for the temporary file to manage the ZIP file | 745 // Create a RAII for the temporary file to manage the ZIP file |
639 TemporaryFile tmp; | 746 TemporaryFile tmp; |
640 | 747 |
641 { | 748 { |
642 // Create a ZIP writer | 749 DicomDirWriter dicomDir; |
750 dicomDir.EnableExtendedSopClass(enableExtendedSopClass); | |
751 | |
643 HierarchicalZipWriter writer(tmp.GetPath().c_str()); | 752 HierarchicalZipWriter writer(tmp.GetPath().c_str()); |
644 writer.SetZip64(isZip64); | 753 writer.SetZip64(commands.IsZip64()); |
645 writer.OpenDirectory("IMAGES"); | 754 |
646 | 755 for (size_t i = 0; i < commands.GetSize(); i++) |
647 // Create a DICOMDIR writer | 756 { |
648 MediaWriterVisitor v(writer, context); | 757 commands.Apply(writer, context, i, dicomDir, IMAGES_FOLDER); |
649 | 758 } |
650 // Request type-3 arguments to be added to the DICOMDIR | |
651 v.dicomDir_.EnableExtendedSopClass(enableExtendedSopClass); | |
652 | |
653 archive.Apply(v); | |
654 | 759 |
655 // Add the DICOMDIR | 760 // Add the DICOMDIR |
656 writer.CloseDirectory(); | |
657 writer.OpenFile("DICOMDIR"); | 761 writer.OpenFile("DICOMDIR"); |
658 std::string s; | 762 std::string s; |
659 v.EncodeDicomDir(s); | 763 dicomDir.Encode(s); |
660 writer.Write(s); | 764 writer.Write(s); |
661 } | 765 } |
766 | |
662 | 767 |
663 // Prepare the sending of the ZIP file | 768 // Prepare the sending of the ZIP file |
664 FilesystemHttpSender sender(tmp.GetPath()); | 769 FilesystemHttpSender sender(tmp.GetPath()); |
665 sender.SetContentType("application/zip"); | 770 sender.SetContentType("application/zip"); |
666 sender.SetContentFilename(filename); | 771 sender.SetContentFilename(filename); |
669 output.AnswerStream(sender); | 774 output.AnswerStream(sender); |
670 | 775 |
671 // The temporary file is automatically removed thanks to the RAII | 776 // The temporary file is automatically removed thanks to the RAII |
672 } | 777 } |
673 }; | 778 }; |
779 | |
780 | |
781 #if 0 | |
782 class ArchiveJob : public IJob | |
783 { | |
784 private: | |
785 ServerContext& context_; | |
786 ArchiveIndex archive_; | |
787 bool isMedia_; | |
788 std::auto_ptr<TemporaryFile> file_; | |
789 std::auto_ptr<HierarchicalZipWriter> writer_; | |
790 std::auto_ptr<IArchiveVisitor> visitor_; | |
791 std::string description_; | |
792 bool started_; | |
793 unsigned int currentInstance_; | |
794 | |
795 public: | |
796 ArchiveJob(ServerContext& context, | |
797 ResourceType level, | |
798 bool isMedia) : | |
799 context_(context), | |
800 archive_(level), | |
801 isMedia_(isMedia), | |
802 started_(false), | |
803 currentInstance_(0) | |
804 { | |
805 } | |
806 | |
807 void SetDescription(const std::string& description) | |
808 { | |
809 description_ = description; | |
810 } | |
811 | |
812 const std::string& GetDescription() const | |
813 { | |
814 return description_; | |
815 } | |
816 | |
817 void AddResource(const std::string& publicId) | |
818 { | |
819 if (started_) | |
820 { | |
821 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
822 } | |
823 | |
824 ResourceIdentifiers resource(context_.GetIndex(), publicId); | |
825 archive_.Add(context_.GetIndex(), resource); | |
826 } | |
827 | |
828 virtual void SignalResubmit() | |
829 { | |
830 LOG(ERROR) << "Cannot resubmit the creation of an archive"; | |
831 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
832 } | |
833 | |
834 virtual void Start() | |
835 { | |
836 if (started_) | |
837 { | |
838 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
839 } | |
840 | |
841 started_ = true; | |
842 | |
843 archive_.Expand(context_.GetIndex()); | |
844 | |
845 const bool isZip64 = IsZip64Required(stats_.GetUncompressedSize(), stats_.GetInstancesCount()); | |
846 | |
847 file_.reset(new TemporaryFile); | |
848 writer_.reset(new HierarchicalZipWriter(file_->GetPath().c_str())); | |
849 writer_->SetZip64(isZip64); | |
850 | |
851 if (isMedia_) | |
852 { | |
853 //visitor_.reset(new | |
854 } | |
855 } | |
856 }; | |
857 #endif | |
674 } | 858 } |
675 | 859 |
676 | 860 |
677 static bool AddResourcesOfInterest(ArchiveIndex& archive, | 861 static bool AddResourcesOfInterest(ArchiveIndex& archive, |
678 RestApiPostCall& call) | 862 RestApiPostCall& call) |