Важное замечание в начале. Основной режим работы 1С в этой статье предполагается 1С 8.3.7 в режиме тонкого клиента без модальных вызовов — самый современный на настоящий момент, на который вскоре должны быть переведены все конфигурации. Также постараюсь описать особенности работы в Веб-Клиенте.
Содержание
Что такое двоичные данные и как с ними можно работать в 1С 8
Двоичные данные (или бинарные) — это файл данных произвольного формата.
Платформа 1С (8.3 и 8.2) в общем случае понятия не имеет, что это. Предполагается, что программист или пользователь знает, какие именно это данные и как их применять. Тем не менее, если в двоичные данные загружен графический файл, формат которого понимает объект типа «Картинка», то при инициализации картинки такими двоичными данными картинка будет нормально показана, а её свойство «Формат» примет правильное значение.
Платформа 1С при работе с двоичными данными может:
- Хранить в базе данных в реквизитах типа «ХранилищеЗначения», в справочниках, документах, регистрах сведений.
- Читать их из файла и записывать в файл.
- Передавать их между сервером и клиентом через временное хранилище.
- Инициализировать ими объект типа «Картинка».
- Закодировать и раскодировать в/из строковое представление Base64.
- Хранить в объектах конфигурации в качестве Макета.
- Читать двоичные данные из сети при помощи объектов типа «HTTPСоединение» (объект «HTTPОтвет» можно получить в том числе в виде двоичных данных), «ПочтовоеВложение», «ИнтернетПочтовоеВложение».
- Зашифровать, расшифровать, подписать и проверить подпись средствами криптографии.
- Вычислить хеш-функцию с помощью объекта типа «ХешированиеДанных»
Возможно, я еще что-то упустил, однако интуитивно ясно, что практически все, что надо для работы с двоичными данными в 1С, у нас есть. Рассмотрим теперь по порядку несколько конкретных примеров работы с двоичными данными на платформе 1С 8.3.
Чтение и запись двоичных данных в файл
Основной тип объектов двоичных данных платформы 1С так и называется: «ДвоичныеДанные». Вот что говорит о нем «Синтаксис-помощник»:
Значение содержит двоичные данные, которые считываются из файла. Значение может быть сохранено в ХранилищеЗначения. Хранимые данные могут быть записаны в файл.
Доступность: Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение(клиент), мобильное приложение(сервер).
Сериализуется. Данный объект может быть сериализован в/из XML. Может использоваться в реквизитах управляемой формы.
Чтение двоичных данных из файла
Тип «Двоичные данные» имеет единственный конструктор:
имяФайла — обязательный аргумент.
В итоге получаем программный объект двоичных данных, прочитанный из файла.
Запись двоичных данных в файл
Определение размера двоичных данных в байтах
Сохранение двоичных данных в реквизит объекта
Рассмотрим сразу запись двоичных данных из файла на клиенте в реквизит объекта базы данных типа ХранилищеЗначения. Причем напишем такой код, который сработает и на веб-клиенте, а также будет лишен модальных вызовов, то есть таких вызовов, которые ожидают действия пользователя и останавливают при этом исполнение программы. Теперь платформа 1С 8.3 требует разрабатывать асинхронные программы.
Выглядит это примерно так: создается обработчик оповещения о выполнении некоторой длительной процедуры, затем запускается процедура «НачатьХХХ()», в которую, кроме понятных аргументов, передается еще и описание обработчика ее завершения. Наша программа спокойно работает далее, а по завершении запущенной процедуры вызывается наш обработчик завершения.
Предположим, у нас на форме есть реквизит типа «СправочникСсылка.Картинки». Справочник «Картинки» имеет реквизит «ДанныеКартинки» типа ХранилищеЗначения.
Создадим команду формы «ЗагрузитьКартинкуИзФайла».
Создадим обработчик команды, выделив команду в списке команд формы и нажав на кнопку с увеличительным стеклом в поле «Действие» панели свойств:
Поскольку все необходимые параметры для записи картинки мы можем передать изнутри клиентской части обработчика, нам нет нужды создавать контекстную серверную процедуру на сервере. Выберем «Создать на клиенте и процедуру на сервере без контекста»:
Вначале напишем наши обработчики команды в старом, «модальном» или «синхронном» стиле:
Получите 267 видеоуроков по 1С бесплатно:
В моей небольшой тестовой конфигурации этот код отлично сработал в режиме тонкого клиента. Теперь преобразуем модальный вызов «ПоместитьФайл» в асинхронный, он же немодальный. В меню конфигуратора запустим команду меню «Текст >Рефакторинг >Нерекомендуемые синхронные вызовы >Преобразовать вызовы модуля». Нам в ответ сообщат, что «Не рекомендуемых синхронных вызовов преобразовано: 1».
Для компактности я удалил все пустые строки, и вот что получилось вместо клиентской части нашего обработчика:
Готово! Мы кошерно асинхронно записали картинку из файла на клиенте в реквизит объекта базы данных, в нашем случае — элемента справочника.
Чтение двоичных данных из объекта БД
Для чего нам надо читать двоичные данные из объекта БД? Наверное, три самых частых случая таковы:
- Внедрить картинку в табличный документ, например, отчет. Табличный документ (отчет) часто формируется на стороне сервера, поэтому нам нет нужды гонять картинки через временное хранилище. Мы просто получаем значение из реквизита типа «хранилище значения», инициализируем им объект типа «Картинка» и помещаем эту картинку в табличный документ. А клиентская сторона приложения отображает уже сформированный табличный документ.
- Отобразить на форме некоторую картинку. Нам надо передать двоичные данные на сторону клиента и загрузить их в реквизит формы при открытии формы. Ну и желательно обновлять картинку по некоторым событиям.
- Сохранить двоичный файл на стороне клиента. Здесь надо получить данные с сервера по некоторой команде и просто сохранить их в файл на клиенте.
Пример 1. Вставить картинки в макет (табличный документ).
Допустим, у нас есть база данных со справочником «Картинки», у элементов которых есть реквизит «Картинка» типа ХранилищеЗначения, содержащий данные картинки.
Создадим новую внешнюю обработку, ее основную форму.
На форме создадим 3 реквизита «СпрКартинка1», «СпрКартинка2», «СпрКартинка3» типа «СправочникСсылка.Картинки» и реквизит «ТабДок» типа «ТабличныйДокумент». Перетащим мышкой эти реквизиты в список элементов формы, чтобы на ней образовались соответствующие поля.
Добавим команду формы «НапихатьКартинок» и создадим ее обработчик. На сей раз выберем «Создать на Клиенте и процедуру на сервере», чтобы не передавать много параметров в процедуру без контекста. Напишем такие обработчики:
И получим примерно такой результат:
Пример 2. Показать картинку из базы данных на форме.
Для демонстрации воспользуемся первой обработкой, где мы записывали файл в БД. Теперь покажем на форме картинку, которая записана в реквизите «Картинка» выбранного на форме элемента справочника «Картинки».
Во-первых, добавим на форму поле, связанное с реквизитом «АдресДанныхКартинки». Например, перетащим мышкой этот реквизит в список элементов формы. Выберем и установим значение свойства «Вид» этого поля в «Поле картинки».
Во-вторых, напишем такую серверную процедуру:
И станем вызывать эту процедуру, например, из обработчика события «При изменении» поля «Картинка»:
Сохранение двоичных данных в файл на клиенте
Думаю, с сохранением двоичных данных из базы данных в файл у Вас проблем не возникнет. По крайней мере, если Вы работаете не в веб-клиенте. Читаем, помещаем во временное хранилище на сервере, затем записываем в файл на клиенте.
Кодирование двоичных данных в формат Base64 и обратно
Тут все очень просто. Платформа имеет две глобальные функции, доступные везде:
Первая получает в качестве аргумента объект типа «ДвоичныеДанные», а возвращает его текстовое представление в кодировке base64, а вторая, наоборот, из текста в формате base64 возвращает объект типа «ДвоичныеДанные».
Не очень, правда, представляю, зачем нам это может понадобиться. Во всех встроенных типах объектов вроде ПочтовоеВложение или объектов для работы с XML необходимые преобразования платформа делает сама. Разве что нам потребуется работать с какими-то нестандартными форматами файлов для обмена с внешними системами…
Итого
На самых простых примерах мы увидели все основные принципы и методы работы с двоичными данными в 1С 8.3. Также коснулись актуальной сейчас темы устранения синхронных вызовов. Остальные возможности работы с двоичными данными Вы без труда реализуете по аналогии с рассмотренными здесь.
Спасибо за внимание. Желаю всем вершин профессионализма и глубин познаний. А главное — чтобы это приносило счастье в жизнь Вашу и окружающих.
Если Вы начинаете изучать 1С программирование, рекомендуем наш бесплатный курс (не забудьте подписаться на YouTube — регулярно выходят новые видео):
К сожалению, мы физически не можем проконсультировать бесплатно всех желающих, но наша команда будет рада оказать услуги по внедрению и обслуживанию 1С. Более подробно о наших услугах можно узнать на странице Услуги 1С или просто позвоните по телефону +7 (499) 350 29 00. Мы работаем в Москве и области.
Считать данные из двоичного файла можно при помощи функции ДвоичныеДанные(ИмяФайла). Например:
Код 1C v 8.2 УП
или через ADODB.Stream
Код 1C v 8.х
Считать данные из двоичного файла можно при помощи функции
ДвоичныеДанные(ИмяФайла). Например:
Код 1C v 8.2 УП
Здесть ДД — специальный объект, который называется "двоичные данные".
В языке 1С есть функция, которая преобразует двоичные данные в строку
Base64Строка(ДвоичныеДанные). Например:
Код 1C v 8.2 УП
Здесть Строка64 — обычная строка, с которой можно делать все, что угодно.
В конце статьи приведена функция Преобразовать64(Строка64 = неопределено, Массив64 = неопределено), которая преобразовывает строку в массив байтов, и обратно.
Для того, чтобы получить массив байтов из строки, вызываем ее так:
Код 1C v 8.2 УП
Для обратного преобразования вызываем так:
Код 1C v 8.2 УП
Преобразовать строку в двоичные данные можно при помощи функции Base64Значение(Строка64)
Все указанные функции, кроме Преобразовать64, являются встроенными функциям платформы.
Далее листинг функции Преобразовать64:
Код 1C v 8.2 УП
Пример: анализ файлов в формате JPEG
Вы можете скачать приложенную обработку прямо сейчас
Постановка задачи
Необходимо просканировать каталог с файлами, выбрать файлы с расширением ".jpg" или ".jpeg" и для каждого такого файла собрать информацию об изображении. Если при анализе выяснится, что файл не соответствует формату JPEG, то такой файл следует пропустить.
Информация, которая нас интересует:
- Ширина изображения в пикселах,
- Высота изображения в пикселах,
- Глубина цвета (количество битов на один пиксел).
Краткое описание формата JPEG
Кратко опишем некоторые детали формата, существенные для решения нашей задачи. За более подробным описанием формата JPEG можно обратиться к соответствующим источникам:
Файл JPEG содержит последовательность маркеров , каждый из которых начинается с байта 0xFF, свидетельствующего о начале маркера, и байта-идентификатора. Некоторые маркеры состоят только из этой пары байтов, другие же содержат дополнительные данные, состоящие из двухбайтового поля с длиной информационной части маркера (включая длину этого поля, но за вычетом двух байтов начала маркера, то есть 0xFF и идентификатора) и собственно данных. Такая структура файла позволяет быстро отыскать маркер с необходимыми данными (например, с длиной строки, числом строк и числом цветовых компонентов сжатого изображения).
Решение
Создадим функцию, которая будет сканировать файл, определять его формат и выделять нужную нам информацию.
Важно, что для корректного разбора маркеры необходимо читать последовательно, один за другим, т.к. байты, совпадающие с маркером могут быть в содержимом фрагментов.
Теперь, когда мы написали основную функцию для анализа JPEG-файла, напишем вспомогательную функцию — ПрочитатьМаркер , которая читает очередной маркер и возвращает информацию о нем:
- РазмерСекции : размер секции, начало которой отмечает маркер
- ЭтоОписаниеИзображения : признак того, что секция, отмеченная маркером, содержит нужную нам информацию об изображении.
Копировать в буфер обмена
И, наконец, соберем всё вместе и напишем функцию, которая будет анализировать все файлы в заданной папке и выдавать полученную информацию в виде таблицы.
Пример: Работа с составными (multipart) HTTP-сообщениями
Вы можете скачать приложенную конфигурацию прямо сейчас
Постановка задачи
В данном примере мы создадим HTTP-сервис, который будет в ответ на запрос от клиента выдавать текстовое сообщение с вложенными картинками. Затем на клиенте мы отобразим полученный ответ.
Ответ от сервиса будет иметь следующий вид:
В этом сообщении надо обратить внимание на тип содержимого (заголовок Content-Type) — "multipart/form-data". Первое слово "multipart" указывает на то, что HTTP-сообщение является составным, т.е. содержит внутри себя несколько вложенных сообщений. Второе слово — "form-data" — указывает на конкретный стандарт составных сообщений, который часто используется для кодирования почтовых сообщений.
В любых составных сообщениях в заголовке Content-Type обязательно должен присутствовать атрибут boundary, определяющий строку, которая отделяет друг от друга вложенные сообщения внутри составного сообщения.
В случае стандарта "multipart/form-data", каждое вложенное сообщение в свою очередь должно содержать заголовок Content-Disposition со значением "form-data" и атрибутом "name", который позволяет идентифицировать сообщения.
Создание cервиса для формирования составного сообщения
Добавим новый HTTP-сервис и назовем его "TestMultipart". Для простоты будем считать, что наш сервис будет возвращать заданное составное сообщение в ответ на любой GET-запрос. Поэтому добавляем Шаблон URL с именем "ДляВсех" и значением "/*". Т.е. данный шаблон соответствует любому запросу. Далее добавляем в шаблон HTTP-метод GET с именем "Get".
В качестве обработчика для метода создаем в модуле сервиса функцию ДляВсех_Get :
Вся работа по созданию сообщения выполняется в функции СоздатьСообщение . Данная функция определяется следующим образом:
У нас есть функция, формирующая составное сообщение и теперь нам осталось только определить две вспомогательные функции для создания вложенных сообщения:
- функция СоздатьСообщение_Текст нужна для создания HTTP-сообщения, содержащего текст,
- функция СоздатьСообщение_Изображение нужна для создания HTTP-сообщения, содержащего изображение.
Копировать в буфер обмена
Разбор составного сообщения на стороне клиента
Теперь посмотрим, как мы можем работать с составными сообщениями на стороне клиента. Нам необходимо распаковать вложенные сообщения и показать их содержимое.
Создаем новую общую форму. На форму добавляем реквизиты типа Строка:
- Сообщение — текст сообщения,
- АдресКартинки1 — адрес первой картинки во временном хранилище,
- АдресКартинки2 — адрес второй картинки во временном хранилище.
Далее добавляем элементы управления:
- Кнопка.
- Поле текстового документа (реквизит Сообщение).
- Поле картинки (реквизит АдресКартинки1).
- Поле картинки (реквизит АдресКартинки2).
Также создаем новую команду формы с именем ОтправитьЗапрос и привязываем команду к кнопке.
Создаем обработчик команды:
Вся работа по запросу сервиса и отображению результата выполняется в серверной функции ВыполнитьЗапрос :
Функция ПрочитатьСообщение содержит самое интересное — разбор полученного от сервиса составного сообщения с использованием новых средств работы с двоичными данными:
Осталось определить вспомогательные функции:
- ПрочитатьЗаголовки — читает заголовки сообщения и представляет их в виде объекта Соответствие
- ПолучитьРазделительСоставногоСообщения — получает разделитель составного сообщения из заголовков сообщения
- ПолучитьИмяСообщения — получает имя вложенного сообщения из заголовков сообщения
Копировать в буфер обмена