При разработке мобильных приложений на платформе 1С:Предприятие разработчики часто сталкиваются с неприятными ошибками на этапе компиляции или выгрузки сборки. Одна из наиболее распространенных ошибок связана с попыткой работы с ZIP-архивами. При попытке сохранить конфигурацию или запустить проверку мобильного приложения система выдает критические ошибки компиляции общего модуля:
{ОбщийМодуль.АвтоОбмен.Модуль(9,16)}: Тип не определен (ЗаписьZipФайла)
{ОбщийМодуль.АвтоОбмен.Модуль(30,18)}: Тип не определен (ЧтениеZipФайла)
В этой статье мы подробно разберем, почему возникает данная проблема, как устроена работа с файлами в мобильном клиенте и мобильной платформе 1С, а также рассмотрим несколько эффективных способов решения — от простого обновления платформы до реализации обходных путей для старых релизов.
Для начала проанализируем исходную ситуацию. Разработчик пытается использовать стандартный код 1С для распаковки или упаковки файлов внутри общего модуля АвтоОбмен на стороне мобильного устройства. Типичный пример такого кода выглядит следующим образом:
Функция ИзвлечьФайл(ИмяАрхива, УдалитьПослеОперации = Ложь)
ИмяФайла = "";
Файл = Новый Файл (ИмяАрхива);
Архив = Новый ЧтениеZipФайла (ИмяАрхива);
Если Архив.Элементы.Количество() > 0 Тогда
Элемент = Архив.Элементы[0];
ИмяФайла = Файл.Путь + Элемент.Имя;
Архив.Извлечь(Элемент, Файл.Путь);
КонецЕсли;
Архив.Закрыть();
Если УдалитьПослеОперации Тогда
Попытка
УдалитьФайлы(ИмяАрхива);
Исключение
КонецПопытки;
КонецЕсли;
Возврат ИмяФайла;
КонецФункции
При попытке сборки мобильного приложения этот код вызывает ошибку синтаксического контроля. Причина кроется в доступности объектов встроенного языка 1С. Если мы обратимся к синтакс-помощнику для объектов ЗаписьZipФайла и ЧтениеZipФайла, то увидим следующее свойство доступности:
Доступность: Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение.
В старых версиях мобильной платформы 1С (включая версию 8.3.10, на которой работал автор вопроса) поддержка объектов для работы с архивами на уровне мобильного клиента и мобильного приложения просто отсутствовала. Платформа 1С «не знает» этих типов данных при компиляции под мобильное устройство, что и приводит к ошибке «Тип не определен».
Рассмотрим современные методы решения этой проблемы, двигаясь от самых простых и правильных к сложным интеграционным обходным путям.
---
Самое важное изменение, о котором необходимо знать каждому разработчику 1С: начиная с версии мобильной платформы 8.3.21, фирма «1С» добавила полноценную поддержку работы с ZIP-архивами непосредственно на мобильных устройствах.
Если в вашей организации или проекте есть возможность обновить версию мобильной платформы (и версию мобильного сборщика) до 8.3.21 или выше, то вам вообще не придется переписывать логику или изобретать обходные пути. Достаточно выполнить следующие действия:
ЗаписьZipФайла и ЧтениеZipФайла исчезнет автоматически, и ваш исходный код заработает без изменений.Однако, что делать, если вы жестко привязаны к старой версии платформы (например, к 8.3.10 или 8.3.14) из-за требований заказчика, устаревшего парка ТСД (терминалов сбора данных) или ограничений операционной системы? Разберем обходные варианты.
---
Если мобильное приложение работает в связке с серверной базой (через HTTP-сервисы или Web-сервисы), то самым надежным архитектурным решением будет перенос всех операций по упаковке и распаковке файлов на сторону сервера 1С.
Рассмотрим по шагам, как организовать этот процесс:
ДвоичныеДанные) и передает на сервер по каналам связи (например, Base64-строкой через HTTP POST-запрос).ЗаписьZipФайла / ЧтениеZipФайла (которые гарантированно поддерживаются на сервере).Чтобы код, предназначенный для сервера, не вызывал ошибок при компиляции мобильного клиента, обязательно используйте инструкции препроцессора (директивы компиляции). Перепишем наш модуль так, чтобы он успешно компилировался везде:
#Если НЕ МобильноеПриложениеКлиент И НЕ МобильноеПриложениеСервер Тогда
Функция ИзвлечьФайлНаСервере(ИмяАрхива, УдалитьПослеОперации = Ложь) Экспорт
ИмяФайла = "";
Файл = Новый Файл (ИмяАрхива);
// Этот код скомпилируется только на обычном сервере/клиенте
Архив = Новый ЧтениеZipФайла (ИмяАрхива);
Если Архив.Элементы.Количество() > 0 Тогда
Элемент = Архив.Элементы[0];
ИмяФайла = Файл.Путь + Элемент.Имя;
Архив.Извлечь(Элемент, Файл.Путь);
КонецЕсли;
Архив.Закрыть();
Если УдалитьПослеОперации Тогда
Попытка
УдалитьФайлы(ИмяАрхива);
Исключение
КонецПопытки;
КонецЕсли;
Возврат ИмяФайла;
КонецФункции
#КонецЕсли
Использование директивы #Если НЕ МобильноеПриложениеКлиент И НЕ МобильноеПриложениеСервер Тогда полностью исключает данный код из сборки мобильного приложения, гарантируя успешную компиляцию без ошибок отсутствия типов.
---
Если ваше мобильное приложение должно работать полностью в автономном режиме (offline) на старой платформе, и у вас нет возможности обращаться к серверу для распаковки файлов, можно применить обходное решение с использованием компоненты Поле HTML-документа и популярной библиотеки JSZip.
Этот элегантный способ позволяет переложить задачу по сжатию и распаковке на движок JavaScript, встроенный в мобильный клиент 1С.
Разберем алгоритм реализации этой схемы:
МакетJSZip).Посмотрим на пример формирования HTML-кода для загрузки в поле:
ШаблонHTML =
"<html>
|<head>
|<script>
|// [Вставьте сюда содержимое библиотеки JSZip из макета]
|</script>
|<script>
|function unzipBase64(base64Data) {
| var zip = new JSZip();
| zip.loadAsync(base64Data, {base64: true}).then(function(contents) {
| // Получаем файлы из архива и передаем их обратно в 1С
| Object.keys(contents.files).forEach(function(filename) {
| zip.file(filename).async('string').then(function(content) {
| // Передача данных обратно в 1С через клик по ссылке или специальный объект
| window.location.href = 'ones://unzipped?name=' + filename + '&data=' + encodeURIComponent(content);
| });
| });
| });
|}
|</script>
|</head>
|<body></body>
|</html>";
Вызов распаковки из встроенного языка 1С выполняется через метод выполнения скрипта в поле HTML-документа. Мы передаем файл, предварительно сконвертировав его в формат Base64:
ДвоичныеДанныеАрхива = Новый ДвоичныеДанные(ПутьКФайлуАрхива);
СтрокаBase64 = ПолучитьBase64СтрокуИзДвоичныхДанных(ДвоичныеДанныеАрхива);
// Вызываем функцию JavaScript внутри HTML-поля
Элементы.ПолеHTMLДокумента.Документ.defaultView.unzipBase64(СтрокаBase64);
Этот метод полностью автономен, работает прямо на мобильном устройстве и не требует обновления платформы 1С.
---
Для мобильных приложений, работающих исключительно на операционной системе Android, доступен еще один обходной путь — использование системных механизмов взаимодействия между приложениями (Intents).
Если на мобильном устройстве установлен любой популярный архиватор (например, RAR, 7-Zip или стандартный файловый менеджер со встроенным ZIP-модулем), мы можем запустить его из кода 1С с передачей параметров командной строки.
Для этого используется метод ЗапуститьПриложение. Рассмотрим пример вызова внешней утилиты:
#Если МобильноеПриложениеКлиент Тогда
// Формируем команду запуска внешнего архиватора
ИмяФайлаАрхива = "/sdcard/Download/exchange.zip";
ПапкаНазначения = "/sdcard/Download/unpacked/";
// Пример команды для вызова установленного архиватора RAR
КомандаЗапуска = "intent:#Intent;action=android.intent.action.VIEW;type=application/zip;S.archive_path=" + ИмяФайлаАрхива + ";S.destination_path=" + ПапкаНазначения + ";end";
Попытка
ЗапуститьПриложение(КомандаЗапуска);
Исключение
Сообщить("Не удалось запустить внешний архиватор: " + ОписаниеОшибки());
КонецПопытки;
#КонецЕсли
Важные нюансы данного метода:
---
Мы подробно проанализировали проблему отсутствия типов архивации в мобильной платформе 1С и изучили возможные варианты ее решения. При выборе стратегии рекомендуем придерживаться следующего плана:
ЗаписьZipФайла и ЧтениеZipФайла заработают в нативном режиме прямо «из коробки».