Пример использования .Net Interop в NAV 2013. Работа с Zip-архивами.

Погружаясь в дебри NAV 2013 натолкнулся на пример того, как можно запаковать, а затем распаковать файлы. Данная возможность находится в программном модуле 8619 Config. Pckg. Compression Mgt (обновленная технология быстрых развертываний). В нем применяется переменная CompressedStream типа DotNet со ссылкой на System.IO.Compression.GZipStream. В результате использования рождались файлы GZip.
Это натолкнуло меня на мысли исследовать возможности по подключения более стандартных способов архивации, в частности классического Zip-архива, который практически является частью операционной системы.
Не думаю, что нарушу какую-либо интригу если сразу скажу – удалось.

Для интересующихся же предлагаю ознакомиться с подробностями.
Для учебных целей я упрощу максимально код, хотя в жизни кое-что придется добавить.
Итак, начнем с простого – объявим переменную типа DotNet.

DN_ZipFile - DotNet: System.IO.Compression.ZipFile.

.NET Type List

Эта переменная позволит нам делать как минимум две базовые операции:

  • Отправлять содержимое выбранного каталога в архив
  • Распаковывать архив в выбранное расположение

Ниже приведены две стоки кода, попробуйте угадать, что делает каждая из них:

DN_ZipFile.CreateFromDirectory('C:\MYDOC\Test', 'C:\MYDOC\Arc1.zip');
DN_ZipFile.ExtractToDirectory('C:\MYDOC\Arc1.zip', 'C:\MYDOC\Test2');

Понятно, что к этим двум строчкам не помешает окружение в виде:

  • Проверить, что директория существует
  • Проверить, что результирующий файл не существует (или удалить его)
  • Проверить, что в итоговом каталоге нет файлов

Для этих целей можно воспользоваться программным модулем 419 File Management.
Стоит заметить, что работа с файлами и архивами происходит вне базы данных, соответственно такое понятия как транзакция на них не распространяется. Это значит, что если при выполнении программного кода возникнет ошибка, то уже выполненные операции с архивами не будут отменены.
Также стоит обратить внимание на свойство переменной RunOnClient, которая отвечает за то, где будет исполняться код на клиенте или сервере.

Properties - RunOnClient

В нашем примере это будет влиять на доступность каталогов. Например, если сервис NAV запущен под Network Service, то шансов, что он сможет создать архив на рабочем столе пользователя нет.

This message is for C/AL programmers: A call to System.IO.Compression.ZipFile.CreateFromDirectory failed with this message: Access to the path ‘C:\Users\apanko\Desktop\Arc1.zip’ is denied.

Если конечно не настроены права на папку и сам путь доступен для сервера, потому как если указать локальный путь, то сервер, запущенный на удаленной машине его попросту не найдет.

Однако продолжим. Как известно аппетит приходит во время еды, и наверняка среди читателей появились желающие создать архив не из директории, а из выбранного файла. Тут код будет чутка сложнее и для начала добавим еще парочку переменных:
DN_ZipFileExt – DotNet: System.IO.Compression.ZipFileExtensions.
DN_ZipArchive - DotNet: System.IO.Compression.ZipArchive.
DN_ZipArchiveMode – DotNet: System.IO.Compression.ZipArchiveMode.

И код будет выглядеть следующим образом:

DN_ZipArchive := DN_ZipFile.Open('C:\MYDOC\Arc2.zip',DN_ZipArchiveMode.Create);
DN_ZipFileExt.CreateEntryFromFile(DN_ZipArchive, 'C:\MYDOC\Test\Test1.xlsx', 'Test1.xlsx');
DN_ZipArchive.Dispose();

Обратите внимание на второй параметр в функции первой строки, он указывает, что будет создан новые файл. В функции Open можно использовать три режима:

  1. Read (Чтение), данные считываются из файла по запросу, используется небольшой буфер.
  2. Create (Создание), данные записываются непосредственно в файл с использованием небольшого буфера. Только одна запись может быть обработана в один момент времени.
  3. Update (Обновление), в этом режиме можно как читать, так и записывать данные в существующий архив, также поддерживаются операции переименования и удаления записей. Однако данный режим требует загрузки всего архива в память, поэтому стоит его использовать только с небольшими архивами и только когда это необходимо.

Почему я обратил ваше внимание на этот момент, да просто потому, что следующие строки кода продемонстрируют как добавить файл в уже существующий архив:

DN_ZipArchive := DN_ZipFile.Open('C:\MYDOC\Arc2.zip',DN_ZipArchiveMode.Update);
DN_ZipFileExt.CreateEntryFromFile(DN_ZipArchive, 'C:\MYDOC\Test\Test1.xlsx', 'Test2.xlsx');

Заметили хитрости:

  1. Метод Dispose, который казался бесполезным в первом куске, при одновременном запуске обоих наборов строк кода доказал свою нужность.
  2. Во втором наборе строк кода был добавлен в архив тот же файл, что и в первом, однако под другим именем.

Ну что ж, пока неплохо. А как насчет работы с файлами в самом архиве, как например извлечь файл по какому-либо условию?
Начнем с объявления недостающей переменной:
DN_ZipArchiveEntry – DotNet: System.IO.Compression.ZipArchiveEntry.

И код:

DN_ZipArchive := DN_ZipFile.OpenRead('C:\MYDOC\Arc1.zip');
iCount := DN_ZipArchive.Entries.Count; //количество файлов в архиве
FOR iii := 1 TO iCount DO BEGIN
  DN_ZipArchiveEntry := DN_ZipArchive.Entries.Item(iii-1);
  IF DN_ZipArchiveEntry.FullName = 'Test2.xlsx' THEN
    DN_ZipFileExt.ExtractToFile(DN_ZipArchiveEntry, 'C:\MYDOC\Test3\Test2.xlsx');
END;

В многочисленных примерах на MSDN рекомендуют при работе с коллекциями, а в DN_ZipArchive.Entries именно коллекция типа System.Collections.ObjectModel.ReadOnlyCollection<ziparchiveentry>, использовать foreach.
Однако такого оператора в NAV нет, пришлось для обхода использовать свойства всех коллекций, такие как Count – количество записей содержащихся в коллекции (архиве), item(N) – конкретная запись из коллекции (внимание – нумерация начинается с 0).
Кстати, кроме имени можно еще для идентификации использовать такие свойства выбранного элемента архива как:
DN_ZipArchiveEntry.Length – обычный размер файла
DN_ZipArchiveEntry.CompressedLength – сжатый размер

И на десерт – удаление файла из архива, очень похоже на извлечение, но есть нюансы – количество элементов в архиве – изменяется в результате удаления:

DN_ZipArchive := DN_ZipFile.Open('C:\MYDOC\Arc2.zip',DN_ZipArchiveMode.Update); 
iii:=1; 
WHILE iii&lt;= DN_ZipArchive.Entries.Count DO BEGIN    
 
  DN_ZipArchiveEntry := DN_ZipArchive.Entries.Item(iii-1); 
  IF DN_ZipArchiveEntry.FullName = 'Audatex2.xlsx' THEN    
 
    DN_ZipArchiveEntry.Delete();    
 
  iii+=1;    
 
END;    
 
DN_ZipArchive.Dispose();

Я уже выдал десерт? Судя по всему – слегка поспешил. Ведь есть еще много интересного, например, как насчет создание архива файлами созданными «на лету»? Внимание на экран:

DN_ZipArchive := DN_ZipFile.Open('C:\MYDOC\Arc3.zip',DN_ZipArchiveMode.Create); 
DN_ZipArchiveEntry := DN_ZipArchive.CreateEntry('Readme.txt');
OutStream := DN_ZipArchiveEntry.Open(); 
OutStream.WRITETEXT('nav4u.ru'); 
DN_ZipArchive.Dispose();

Обратили внимание как был создан архив, в нем пустой файл, который затем был открыт на запись как поток  и наполнен крайне полезным содержимым.

На этом завершен один из примеров использования такой технологии как .Net Interopability в NAV 2013.

Метки: ,



Комментариев: 2

  1. Дмитрий пишет:

    Подскажите. А как начать изучение nav, если версии для обучения не существует. Подскажите советом для начинающихю Заранее спасибо за ответ.

  2. apanko пишет:

    Добрый день, Дмитрий,

    Так как это корпоративное приложение, то вариант фактически один - через компанию.
    1. Устроиться на работу в компанию, где используют приложение. Выучить пользовательский функционал.
    Там же можно получить доступ к материалам: референсная версия, справочные материалы, часто остаются стандартные учебные материалы. Если есть поддержка от партнера, то можно запросить указанные материалы у них.
    Недостаток: мало шансов выучить разработку. много шансов выучить сильно модифицированную версию.

    2. Устроиться на работу в компанию, которая внедряет приложение. Выбрать направление - консультант или разработчик, пройти обучение внутри компании. Стать специалистом.
    Недостаток: без опыта можно оказаться на несильно оплачиваемой позиции стажера.

    Учитывая стоимость курсов, вариантов учиться самому практически нет. Это иллюзия.

    Есть еще модификация варианта 1 - попасть в компанию, где только начинается проект внедрения и попасть в команду, которая отвечает за внедрения со стороны заказчика. Есть хорошие шансы получить верный старт.

Оставьте свой отзыв!