Асинхронная функция. Дописывает вложения существующий PDF-файл. Если в документе уже существуют вложения с именами, указанными в коллекции вложений, то вложения в документе заменяются на вложения из коллекции. Используется только при записи в форматы PDF и PDF/A-3. Если документ записывается в формате PDF или PDF/A-3 и указан параметр <Вложения>, то вложения добавляются в документ в формате PDF и PDF/A-3. При записи вложений в документы форматов PDF/A-1 и PDF/A-2 генерируется исключение.
Синтаксис
ЗаписатьВложенияАсинх(<Вложения>)Полное описание, параметры и ограничения
ЗаписьPDF.ЗаписатьВложенияАсинх (PDFWriter.WriteAttachmentsAsync)
ЗаписьPDF (PDFWriter)
ЗаписатьВложенияАсинх (WriteAttachmentsAsync)
Доступен, начиная с версии 8.3.18.
Синтаксис:
ЗаписатьВложенияАсинх(<Вложения>)
Параметры:
<Вложения> (обязательный)
Тип: КоллекцияВложенийPDF.
Объект, содержащий вложения PDF-документа.
Возвращаемое значение:
Тип: Обещание.
Результат выполнения обещания - Неопределено.
Описание:
Асинхронная функция. Дописывает вложения существующий PDF-файл. Если в документе уже существуют вложения с именами, указанными в коллекции вложений, то вложения в документе заменяются на вложения из коллекции.
Используется только при записи в форматы PDF и PDF/A-3.
Если документ записывается в формате PDF или PDF/A-3 и указан параметр <Вложения>, то вложения добавляются в документ в формате PDF и PDF/A-3.
При записи вложений в документы форматов PDF/A-1 и PDF/A-2 генерируется исключение.
Доступность:
Тонкий клиент, толстый клиент.
См. также:
ЗаписьPDF, метод ЗаписатьВложения
ЗаписьPDF, метод НачатьЗаписьВложений
ДокументPDF, метод Записать
ДокументPDF, метод ЗаписатьАсинх
Использование в версии:
Доступен, начиная с версии 8.3.18.
Описание изменено в версии 8.3.21.
Методическая информация
Практические примеры
Асинхронно добавить JSON в свой PDF
Открываем собственный поток записи через Ждать, дописываем вложение и ожидаем закрытие. Проверку выполняет другой PDF-объект после завершения записи.
Где и как запускать
Модуль пустой управляемой формы учебной внешней обработки; тонкий или толстый клиент Windows. Вставьте весь модуль. Это не серверный код.
Подготовка
Создайте учебную внешнюю обработку с пустой управляемой основной формой. Создайте команду УчебныйПример и кнопку этой команды.
В свойстве команды Действие выберите процедуру УчебныйПример. Вставьте полный приведённый модуль формы.
Откройте EPF в тонком или толстом клиенте Windows и нажмите кнопку. Не переносите Ждать и Асинх в серверный общий модуль.
Пример работает только со своими данными в памяти; записи в базу, файлы и сеть нет.
Документ PDF строится из собственной ячейки Книга: 3 шт. Внешний PDF, установленный PDF-редактор, криптографический сертификат и реальные персональные данные не нужны.
Файловый путь нигде не используется. Для просмотра в PDF-программе сохраните только полученные собственные двоичные данные в отдельно выбранный новый учебный файл.
&НаКлиенте
Асинх Процедура УчебныйПример(Команда)
Чтение = Неопределено;
Запись = Неопределено;
ПотокЧтения = Неопределено;
ПотокPDF = Новый ПотокВПамяти;
Документ = Новый ТабличныйДокумент;
Документ.Область("A1").Текст = "Книга: 3 шт.";
Документ.Область("A1").ЦветТекста = Новый Цвет(30, 90, 180);
Попытка
Ждать Документ.ЗаписатьАсинх(ПотокPDF, ТипФайлаТабличногоДокумента.PDF);
Вложения = Новый КоллекцияВложенийPDF;
ТекстJSON = "{""товар"":""Книга"",""количество"":3}";
БайтыJSON = ПолучитьДвоичныеДанныеИзСтроки(ТекстJSON, КодировкаТекста.UTF8, Ложь);
Вложения.Добавить("товар.json", БайтыJSON, "application/json", ТипСвязиВложенияPDF.Данные);
ПотокPDF.Перейти(0, ПозицияВПотоке.Начало);
Запись = Новый ЗаписьPDF;
Ждать Запись.ОткрытьАсинх(ПотокPDF);
Ждать Запись.ЗаписатьВложенияАсинх(Вложения);
Ждать Запись.ЗакрытьАсинх();
Запись = Неопределено;
БайтыPDF = ПотокPDF.ЗакрытьИПолучитьДвоичныеДанные();
ПотокPDF = Неопределено;
ПотокЧтения = БайтыPDF.ОткрытьПотокДляЧтения();
Чтение = Новый ЧтениеPDF;
Ждать Чтение.ОткрытьАсинх(ПотокЧтения);
Прочитанные = Ждать Чтение.ПолучитьВложенияАсинх();
ФайлJSON = Прочитанные.Найти("товар.json");
Если ФайлJSON = Неопределено Тогда
ВызватьИсключение "Нет вложения после завершённой асинхронной записи";
КонецЕсли;
Сообщить(Прочитанные.Количество() = 1);
Сообщить(ПолучитьСтрокуИзДвоичныхДанных(ФайлJSON.Содержимое, КодировкаТекста.UTF8) = ТекстJSON);
Исключение
Если Чтение <> Неопределено Тогда
Ждать Чтение.ЗакрытьАсинх();
КонецЕсли;
Если Запись <> Неопределено Тогда
Ждать Запись.ЗакрытьАсинх();
КонецЕсли;
Если ПотокЧтения <> Неопределено Тогда
ПотокЧтения.Закрыть();
КонецЕсли;
Если ПотокPDF <> Неопределено Тогда
ПотокPDF.Закрыть();
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
Если Чтение <> Неопределено Тогда
Ждать Чтение.ЗакрытьАсинх();
КонецЕсли;
Если Запись <> Неопределено Тогда
Ждать Запись.ЗакрытьАсинх();
КонецЕсли;
Если ПотокЧтения <> Неопределено Тогда
ПотокЧтения.Закрыть();
КонецЕсли;
Если ПотокPDF <> Неопределено Тогда
ПотокPDF.Закрыть();
КонецЕсли;
КонецПроцедурыРазбор по шагам
Сначала ожидаем экспорт исходного PDF без вложений.
Создаём неинициализированный ЗаписьPDF; каждую следующую операцию выполняем после Ждать предыдущей.
Запись и её закрытие завершаются до получения итоговых байтов из потока.
Новый ЧтениеPDF независимо подтверждает имя и содержимое вложения; выводим именно результат, не объект Обещание.
Как проверить результат
Две проверки Истина; JSON проверен после завершения записи.
Файл товар.json на диске не создаётся; все байты принадлежат этой форме.
Ожидаемый результат
Асинхронная запись и независимая проверка завершены в правильном порядке.
На что обратить внимание
Обещание не является признаком уже завершённой записи: требуется Ждать.
Нельзя освобождать поток, пока асинхронная операция PDF ещё использует его.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Асинхронно изменить только свой PDF: вложение, штамп, серый цвет и удаление
Полная клиентская последовательность с Ждать. Результат читается и показывается только после ЗакрытьАсинх, а собственное вложение удаляется точным именем.
Где и как запускать
Полный модуль управляемой формы внешней обработки, толстый клиент Windows; свой файл на клиенте.
Подготовка
Работайте только в отдельной своей конфигурации УчебнаяКонфигурацияСинтаксиса, 8.5.1.1343. Исходная таблица Книга / 3 / 250 / 750 создаётся полностью в коде.
Для синхронных уроков вставьте полный модуль в серверный общий модуль УчебныеФайлыPDF и вызовите ВыполнитьПример() своей серверной командой. Новый временный файл будет на серверной машине, не обязательно на вашем ПК.
Для асинхронного и callback-урока вставьте полный код в модуль управляемой формы внешней обработки. Создайте команду Выполнить, обработчик Выполнить, кнопку. Используйте толстый клиент Windows; файл создаётся на клиентской машине.
Код сначала получает новое временное имя, проверяет отсутствие файла и выводит точный путь. Только после этого записывает собственные PDF-байты. Рабочий или выбранный пользователем PDF нигде не запрашивается.
ЗаписьPDF изменяет именно созданный этим запуском файл. Чтение результата начинается после закрытия записи. Файл оставляется пользователю для просмотра и ручного удаления; автоматического удаления нет.
Удаление вложений допустимо начиная с PDF 1.5. Пример проверяет первые восемь символов собственного файла перед этой операцией. Для PDF/A-1 или PDF/A-2 произвольные CSV-вложения не подходят.
До завершения асинхронной цепочки форму не закрывайте и второй запуск не выполняйте. При ошибке начала шага успех не объявляется. Ни создание пособия, ни его Python-тесты этот код в 1С не выполняют.
Перем Занято;
Перем СобственныйPDF;
&НаСервереБезКонтекста
Функция СоздатьСобственныеБайтыPDF()
Таблица = Новый ТабличныйДокумент;
Таблица.КодЯзыка = "ru";
Таблица.Область(1, 1).Текст = "СОБСТВЕННЫЙ УЧЕБНЫЙ ОБРАЗЕЦ";
Таблица.Область(2, 1).Текст = "Книга";
Таблица.Область(2, 2).Текст = "3";
Таблица.Область(2, 3).Текст = "250";
Таблица.Область(2, 4).Текст = "750";
Таблица.Область(1, 1, 2, 4).ЦветФона = Новый Цвет(255, 255, 210);
Таблица.Область(, 1, , 1).ШиринаКолонки = 45;
Поток = Новый ПотокВПамяти;
Попытка
Таблица.Записать(Поток, ТипФайлаТабличногоДокумента.PDF);
Данные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
Исключение
Поток.Закрыть();
ВызватьИсключение;
КонецПопытки;
Возврат Данные;
КонецФункции
&НаКлиенте
Функция СоздатьСвойФайлPDF(Данные)
Имя = ПолучитьИмяВременногоФайла("pdf");
Проверка = Новый Файл(Имя);
Если Проверка.Существует() Тогда
ВызватьИсключение "Новое имя уже занято: перезапись запрещена";
КонецЕсли;
Сообщить("Создаётся только собственный PDF: " + Имя);
Данные.Записать(Имя);
Возврат Имя;
КонецФункции
&НаКлиенте
Функция ПрочитатьСвоиВложения(Имя)
Чтение = Новый ЧтениеPDF(Имя);
Попытка
Вложения = Чтение.ПолучитьВложения();
Чтение.Закрыть();
Исключение
Чтение.Закрыть();
ВызватьИсключение;
КонецПопытки;
Возврат Вложения;
КонецФункции
&НаКлиенте
Процедура ПроверитьУчебнуюВерсию(Имя)
Чтение = Новый ЧтениеДанных(Имя, КодировкаТекста.UTF8);
Попытка
Заголовок = Чтение.ПрочитатьСимволы(8);
Чтение.Закрыть();
Исключение
Чтение.Закрыть();
ВызватьИсключение;
КонецПопытки;
Если СтрДлина(Заголовок) <> 8 Или Лев(Заголовок, 5) <> "%PDF-" Или Сред(Заголовок, 7, 1) <> "." Тогда
ВызватьИсключение "Учебный заголовок PDF не распознан";
КонецЕсли;
Старшая = Число(Сред(Заголовок, 6, 1));
Младшая = Число(Сред(Заголовок, 8, 1));
Если Старшая < 1 Или (Старшая = 1 И Младшая < 5) Тогда
ВызватьИсключение "Удаление вложений требует PDF 1.5 или новее";
КонецЕсли;
Сообщить("Заголовок собственного файла: " + Заголовок);
КонецПроцедуры
&НаКлиенте
Функция СоздатьСвоёВложение(Текст)
Вложения = Новый КоллекцияВложенийPDF;
Данные = ПолучитьДвоичныеДанныеИзСтроки(Текст, КодировкаТекста.UTF8, Ложь);
Вложения.Добавить("guide-owned-book.csv", Данные, "text/csv", ТипСвязиВложенияPDF.Данные);
Возврат Вложения;
КонецФункции
&НаКлиенте
Процедура ПроверитьСвоюСтраницу(Данные)
Поток = Данные.ОткрытьПотокДляЧтения();
Попытка
Документ = Новый ДокументPDF;
Документ.Прочитать(Поток);
Поток.Закрыть();
Исключение
Поток.Закрыть();
ВызватьИсключение;
КонецПопытки;
Если Документ.КоличествоСтраниц() = 0 Тогда
ВызватьИсключение "Нет собственной страницы для штампа";
КонецЕсли;
Первая = Документ.Страницы.Получить(0);
Если Первая.Ширина < 80 Или Первая.Высота < 65 Тогда
ВызватьИсключение "Собственная страница меньше прямоугольника штампа";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция СоздатьСобственныйШтамп()
ТаблицаШтампа = Новый ТабличныйДокумент;
ТаблицаШтампа.КодЯзыка = "ru";
ТаблицаШтампа.Область(1, 1).Текст = "ОБРАЗЕЦ — НЕ ДОКУМЕНТ";
ТаблицаШтампа.Область(1, 1).ЦветФона = Новый Цвет(210, 240, 255);
Описание = Новый ОписаниеОтображаемогоОбъектаPDF;
Описание.Имя = "guide-owned-stamp";
Описание.Объект = ТаблицаШтампа;
Описание.НомерСтраницы = 1;
Описание.Лево = 10;
Описание.Верх = 45;
Описание.Ширина = 60;
Описание.Высота = 10;
Возврат Описание;
КонецФункции
&НаКлиенте
Асинх Процедура Выполнить(Команда)
Если Занято = Истина Тогда
ВызватьИсключение "Дождитесь завершения своей записи";
КонецЕсли;
Данные = СоздатьСобственныеБайтыPDF();
ПроверитьСвоюСтраницу(Данные);
Имя = СоздатьСвойФайлPDF(Данные);
ПроверитьУчебнуюВерсию(Имя);
Вложения = СоздатьСвоёВложение("Книга;3;250;750");
Описание = СоздатьСобственныйШтамп();
Имена = Новый Массив;
Имена.Добавить("guide-owned-book.csv");
Запись = Новый ЗаписьPDF;
Занято = Истина;
Попытка
Ждать Запись.ОткрытьАсинх(Имя);
Ждать Запись.ЗаписатьВложенияАсинх(Вложения);
Ждать Запись.ЗаписатьОтображаемыйОбъектАсинх(Описание);
Ждать Запись.ПреобразоватьВОттенкиСерогоАсинх();
Ждать Запись.ЗаписатьУдалениеВложенийАсинх(Имена);
Ждать Запись.ЗакрытьАсинх();
Занято = Ложь;
Исключение
ОшибкаОперации = ОписаниеОшибки();
Попытка
Запись.Закрыть();
Занято = Ложь;
Исключение
ОшибкаОперации = ОшибкаОперации + Символы.ПС + "Ошибка закрытия: " + ОписаниеОшибки();
КонецПопытки;
ВызватьИсключение ОшибкаОперации;
КонецПопытки;
Итог = ПрочитатьСвоиВложения(Имя);
Сообщить(Итог.Количество() = 0);
СобственныйPDF = Новый ДокументPDF;
СобственныйPDF.Прочитать(Имя);
Сообщить(СобственныйPDF.КоличествоСтраниц() > 0);
СобственныйPDF.Показать("guide-owned: асинхронный писатель PDF", "");
КонецПроцедурыРазбор по шагам
Создать свой файл на клиенте из PDF-байтов собственной серверной таблицы. Проверить страницу для штампа и заголовок версии.
Дождаться открытия и записи своего вложения. Отдельно дождаться штампа и преобразования в серый.
Удалить только известное собственное имя массивом строк, дождаться закрытия писателя.
Повторно прочитать вложения и документ, показать своё окно. При ошибке закрыть собственную запись; если закрытие не удалось, повторный запуск остаётся заблокирован.
Как проверить результат
Две структурные проверки дают Истина: итоговых вложений 0, страницы есть.
В окне guide-owned: асинхронный писатель PDF вручную проверить книгу, учебный штамп и серую подложку. Свой файл оставлен по выведенному пути.
Ожидаемый результат
Все некриптографические асинхронные операции PDF-писателя соединены настоящей собственной задачей, не набором независимых вызовов над неизвестным объектом.
На что обратить внимание
Флаг занятости ставится до асинхронной цепочки и не снимается при неподтверждённом закрытии записи.
У ЗаписатьОтображаемыйОбъектAsync нет второго аргумента учёта ориентации, как у ДокументPDF: не переносите сигнатуру другого класса.
После удаления вложения его старые байты могут оставаться в инкрементальной истории PDF. Это не безопасное стирание данных.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.