Начиная с версии технологической платформы 8.3.9 средства для работы с двоичными данными претерпели существенные изменения. В этой статье я постараюсь рассказать как о старых, так и о новых инструментах для работы с двоичными данными. При написании статьи использовалась версия технологической платформы 8.3.12
Общая информация
Если раньше, до версии технологической платформы 8.3.9, мы располагали только объектом ДвоичныеДанные, то к настоящему времени у нас имеется целый набор объектов, которые серьезно расширяют наши возможности по манипуляциям с двоичными данными. Рассмотрим все эти объекты чуточку подробнее.
Двоичные данные
Экземпляры объекта ДвоичныеДанные содержат двоичные данные, которые считываются из файла. При это объект ДвоичныеДанные является достаточно многофункциональным — мы можем:
- читать двоичные данные из файла и записывать их в файл;
- передавать их между клиентом и сервером при помощи временного хранилища;
- передавать и получать их по сети;
- хранить их базе данных в реквизитах вида ХранилищеЗначения;
- превратить двоичные данные в объект вида Картинка (при определенных условиях конечно);
- хранить двоичные данные в макетах;
- шифровать и расшифровывать, подписывать и проверять подписи;
Наверняка я что-то пропустил, но главное должно быть понятно — несмотря на значительное развитие средств работы с двоичными данными, объект ДвоичныеДанные остается ключевым.
Потоки
Это группа объектов назначение которых заключается в работе с потоками данных.
Поток — этот объект представляет собой поток данных из которого можно читать и/или записывать в него данные. Данный объект не имеет конструктора, а получить экземпляр объекта можно при помощи различных методов других объектов.
ФайловыйПоток — специализированный вариант объекта Поток, предназначенный для работы с данными находящимися в файлах на диске.
ПотокВПамяти — специализированный вариант объекта Поток, предназначенный для работы с данными находящимися в оперативной памяти.
МенеджерФайловыхПотоков — этот объект предоставляет типовые методы для работы с файлами (открытие и создание). Создать экземпляр этого объекта нельзя — имеется объект глобального контекста ФайловыеПотоки который и предоставляет доступ к методам менеджера.
Чтение и запись
ЧтениеДанных — этот объект предназначен для чтения различных типов данных из различных источников (потоки, файлы, двоичные данные).
РезультатЧтенияДанных — этот объект содержит описание результата чтения данных из потока. Объект не имеет конструктора, получить экземпляр объекта можно при помощи методов других объектов.
БуферДвоичныхДанных — этот объект представляет собой коллекцию байтов фиксированного размера, имеется возможность произвольного доступа и изменения по месту.
ЗаписьДанных — этот объект предназначен для записи различных типов данных в приемник.
Практическая часть
Итак, у нас достаточно много различных объектов, которые, в свою очередь, имеют много разных свойств и методов. Разобраться во всем этом более подробно помогут практические примеры, к ним и перейдем.
Многие объекты — ДвоичныеДанные, Поток, ФайловыйПоток, ПотокВПамяти, ЧтениеДанных, ЗаписьДанных, РезультатЧтенияДанных имеют пары синхронных и асинхронных методов, например: Записать — НачатьЗапись, Закрыть — НачатьЗакрытие. Асинхронные методы нужны для обеспечения возможности одинаковой работы и в тонком клиенте, и в веб-клиенте.
Подробнее про синхронные и асинхронные методы можно прочесть в этой статье.
Двоичные данные
Ниже приведены примеры основных операций с объектом ДвоичныеДанные.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | &НаКлиенте Процедура РаботаСДвоичнымиДаннымиВ1С(Команда) //создаем двоичные данные из файла ДвоичныеДанные = Новый ДвоичныеДанные("D:\test.png"); //получаем размер двоичных данных Сообщить("Размер файла: "+ДвоичныеДанные.Размер()+" байт"); //кодируем двоичные данные в строку по алгоритму base64 СтрокаBase64 = Base64Строка(ДвоичныеДанные); //и раскодируем обратно ДвоичныеДанные = Base64Значение(СтрокаBase64); Сообщить(СтрокаBase64); //создаем картинку из двоичных данных Картинка = Новый Картинка(ДвоичныеДанные); //помещаем во временное хранилище и передаем адрес на сервер ПолучитьДвоичныеДанныеНаСервере(ПоместитьВоВременноеХранилище(ДвоичныеДанные)); КонецПроцедуры &НаСервере Процедура ПолучитьДвоичныеДанныеНаСервере(Адрес) //получаем двоичные данные из временного хранилища ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес); //записываем двоичные данные в файл на сервере ДвоичныеДанные.Записать("D:\serv-test.png"); //помещаем двоичные данные в объект ХранилищеЗначения Хранилище = Новый ХранилищеЗначения(ДвоичныеДанные); КонецПроцедуры |
Потоки
В начале создадим файловый поток из PNG-файла и прочитаем первые 8 байт — они у изображений в формате PNG всегда такие: 137,80,78,71,13,10,26,10. При создании объекта ЧтениеДанных указан порядок байтов — BigEndian, подробнее об этом можно прочесть тут.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | &НаКлиенте Процедура РаботаСПотокамиВ1С(Команда) //создадим фаловый поток ФайловыйПоток = ФайловыеПотоки.ОткрытьДляЧтения("D:\test.png"); //размер файла Сообщить("Размер файла: "+ФайловыйПоток.Размер()+" байт"); //создадим необходимый объект для чтения данных из потока ЧтениеДанных = Новый ЧтениеДанных(ФайловыйПоток, КодировкаТекста.ANSI, ПорядокБайтов.BigEndian); //считаем первые восемь байт в буфер Буфер = ЧтениеДанных.ПрочитатьВБуферДвоичныхДанных(8); //пройдемся по каждому байту буфера Для Каждого Байт Из Буфер Цикл Сообщить(Строка(Байт)); КонецЦикла; //этот цикл делает тоже самое что и предыдущий Для Номер = 0 По 7 Цикл Сообщить(Строка(Буфер[Номер])); КонецЦикла; КонецПроцедуры |
Теперь попробуем отправить составное (multipart) HTTP-сообщение. У меня на сервере есть PHP-скрипт вот такого содержания:
1 2 3 4 5 6 | echo $_FILES['image1']['name']."\n"; echo $_FILES['image1']['size']."\n"; echo $_FILES['image2']['name']."\n"; echo $_FILES['image2']['size']; ?> |
Отошлем ему две картинки из библиотеки картинок и посмотрим, что получится:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | &НаКлиенте Процедура Проверить3(Команда) //подготавливаем вложенные сообщения ДвоичныеДанные1 = ПодготовитьКартинку("image1", "image1.png", БиблиотекаКартинок.АктивироватьЗадачу); ДвоичныеДанные2 = ПодготовитьКартинку("image2", "image2.png", БиблиотекаКартинок.АктивныеПользователи); Разделитель = "boundary"; //устанавливаем заголовки основного сообщения Заголовки = Новый Соответствие(); Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель); //формируем основное сообщение ПотокВПамяти = Новый ПотокВПамяти(); ЗаписьДанных = Новый ЗаписьДанных(ПотокВПамяти); ЗаписьДанных.ЗаписатьСтроку("--"+Разделитель); ЗаписьДанных.Записать(ДвоичныеДанные1); ЗаписьДанных.ЗаписатьСтроку(""); ЗаписьДанных.ЗаписатьСтроку("--"+Разделитель); ЗаписьДанных.Записать(ДвоичныеДанные2); ЗаписьДанных.ЗаписатьСтроку(""); ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--"); ЗаписьДанных.Закрыть(); ТелоЗапроса = ПотокВПамяти.ЗакрытьИПолучитьДвоичныеДанные(); //отправляем данные скрипту Соединение = Новый HTTPСоединение("server.ru",443,,,,,Новый ЗащищенноеСоединениеOpenSSL); Запрос = Новый HTTPЗапрос("/script.php", Заголовки); Запрос.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса); Ответ = Соединение.ОтправитьДляОбработки(Запрос); Сообщить(Ответ.ПолучитьТелоКакСтроку()); КонецПроцедуры &НаКлиенте Функция ПодготовитьКартинку(Название, ИмяФайла, Картинка) Поток = Новый ПотокВПамяти(); ЗаписьДанных = Новый ЗаписьДанных(Поток); //устанавливаем заголовки ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=" + Название + "; filename=" + ИмяФайла); ЗаписьДанных.ЗаписатьСтроку("Content-Type: image/png"); ЗаписьДанных.ЗаписатьСтроку(""); ЗаписьДанных.Записать(Картинка.ПолучитьДвоичныеДанные()); ЗаписьДанных.Закрыть(); Возврат Поток.ЗакрытьИПолучитьДвоичныеДанные(); КонецФункции |
Полезные ссылки: о работе с HTTP в 1С, о составных HTTP-сообщениях.
Результат:
На этом все, надеюсь, что эта статья Вам помогла.
Загрузка...
нихрена не понял.
как из входящих писем вытащить вложения и прикрепить их как файлы к внутр.доку-ту в 1С документообороте???
уже неделю зависаю.
Email = Новый ИнтернетПочта;
Email.Подключиться(Профиль,ПротоколИнтернетПочты.IMAP);
МассивВходящихПисем = Новый Массив;
МассивВходящихПисем = Email.Выбрать(Ложь,,Ложь);
Для каждого Письмо Из МассивВходящихПисем Цикл
Если СтрНайти(Письмо.Тема,»Заявка на доработку ИС»)>0 Тогда
Сообщить(«Нашлось письмо по Заявке на доработку ИС»);
Заявка = Справочники.ВнутренниеДокументы.СоздатьЭлемент();
Заявка.ВидДокумента = Справочники.ВидыВнутреннихДокументов.НайтиПоНаименованию(«Заявка на доработку ИС»);
Заявка.ДатаСоздания = ТекущаяДата();
ШаблоныДокументов.ЗаполнитьРеквизитыДокументаПоШаблону(
Справочники.ШаблоныВнутреннихДокументов.НайтиПоНаименованию(«Заявка на доработку ИС»),Заявка);
Заявка.Содержание = Письмо.Тексты[0].Текст;
Заявка.Подготовил = Заявка.Ответственный;
Заявка.Записать();
что дальге надо писать??? прикрепленные файлы находятся в Письмо.Вложения[].Данные (это и есть двлич.данные)….как из них получить файл и потом прикрутить к Заявке?
вот это вот не работает:
ВложенияВоВременномХранилище = РаботаСПочтовымиСообщениямиСлужебный.ОписанияВложений(Письмо);
РаботаСФайламиСлужебныйВызовСервера.УстановитьВладельцаФайла(ВложенияВоВременномХранилище,Заявка);
Была похожая задачка.
Проверял входящие по отправителю, выдёргивал вложения и складывал в директорию.
Потом пробегал по файлам (excel), через табдок считывал внутренности и записывал в бд.
В твоём случае, в объекте письмо должно находиться вложение.
Это вложение нужно записать как файл (временный файл) и прочитать через двоичные данные.
И ещё: для вложений лучше использовать отдельный справочник, а в документе оставлять ссылку (адрес) на элемент справочника.
Таким образом ты немного облегчишь документ. Удачи!
Ну наверно так считать
ИмяВременногоФайла = КаталогВременныхФайлов()+»Вложение.bin»;
Письмо.Вложения[0].Данные.Записать(ИмяВременногоФайла);
а уж как прикрутить, то во «внутреннем документе» наверно есть какое-то поле, куда его можно загрузить
Это плохой метод через каталог. Ошибки совместного доступа к файлам не миновать частым
Как взять поток с COM порта?
Получить объект порта и слушать, что там происходит.
Не могу понять, как превратить картинку в двоичные данные без файла?
У меня картинка генерится в самой эске и не вижу смысла использовать промежуточный файл, чтобы получить двоичные данные.
Картинка — qrcode. После генерации вставляю в область для qrкода.
Глупость делал. Не надо ничего превращать.
Нужно просто использовать картинку как есть.
В моём случае — вставить в реквизит табличного документа.