Проверяем версию собственного PDF, добавляем учебный CSV, затем удаляем ровно его имя массивом строк и читаем результат.
Где и как запускать
Полный серверный общий модуль УчебныеФайлыPDF; свой файл на серверной машине.
Подготовка
Работайте только в отдельной своей конфигурации УчебнаяКонфигурацияСинтаксиса, 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()
Таблица = Новый ТабличныйДокумент;
Таблица.КодЯзыка = "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, Ложь);
Вложения.Добавить("guide-owned-book.csv", Данные, "text/csv", ТипСвязиВложенияPDF.Данные);
Возврат Вложения;
КонецФункции
Функция ПрочитатьСвоиВложения(Имя)
Чтение = Новый ЧтениеPDF(Имя);
Попытка
Вложения = Чтение.ПолучитьВложения();
Чтение.Закрыть();
Исключение
Чтение.Закрыть();
ВызватьИсключение;
КонецПопытки;
Возврат Вложения;
КонецФункции
Процедура ПроверитьУчебнуюВерсию(Имя)
Чтение = Новый ЧтениеДанных(Имя, КодировкаТекста.UTF8);
Попытка
Заголовок = Чтение.ПрочитатьСимволы(8);
Чтение.Закрыть();
Исключение
Чтение.Закрыть();
ВызватьИсключение;
КонецПопытки;
Если СтрДлина(Заголовок) <> 8 Или Лев(Заголовок, 5) <> "%PDF-" Или Сред(Заголовок, 7, 1) <> "." Тогда
ВызватьИсключение "Учебный заголовок PDF не распознан";
КонецЕсли;
Старшая = Число(Сред(Заголовок, 6, 1));
Младшая = Число(Сред(Заголовок, 8, 1));
Если Старшая < 1 Или (Старшая = 1 И Младшая < 5) Тогда
ВызватьИсключение "Удаление вложений требует PDF 1.5 или новее";
КонецЕсли;
Сообщить("Заголовок собственного файла: " + Заголовок);
КонецПроцедуры
Процедура ВыполнитьПример() Экспорт
Имя = СоздатьСвойФайлPDF(СоздатьСобственныеБайтыPDF());
ПроверитьУчебнуюВерсию(Имя);
Запись = Новый ЗаписьPDF(Имя);
Попытка
Запись.ЗаписатьВложения(СоздатьСвоёВложение("Книга;3;250;750"));
Запись.Закрыть();
Исключение
ОшибкаОперации = ОписаниеОшибки();
Попытка
Запись.Закрыть();
Исключение
ОшибкаОперации = ОшибкаОперации + Символы.ПС + "Ошибка закрытия: " + ОписаниеОшибки();
КонецПопытки;
ВызватьИсключение ОшибкаОперации;
КонецПопытки;
ДоУдаления = ПрочитатьСвоиВложения(Имя);
Сообщить(ДоУдаления.Количество() = 1);
Имена = Новый Массив;
Имена.Добавить("guide-owned-book.csv");
Запись = Новый ЗаписьPDF(Имя);
Попытка
Запись.ЗаписатьУдалениеВложений(Имена);
Запись.Закрыть();
Исключение
ОшибкаОперации = ОписаниеОшибки();
Попытка
Запись.Закрыть();
Исключение
ОшибкаОперации = ОшибкаОперации + Символы.ПС + "Ошибка закрытия: " + ОписаниеОшибки();
КонецПопытки;
ВызватьИсключение ОшибкаОперации;
КонецПопытки;
ПослеУдаления = ПрочитатьСвоиВложения(Имя);
Сообщить(ПослеУдаления.Количество() = 0);
Сообщить("Собственный PDF сохранён без собственного вложения: " + Имя);
КонецПроцедурыРазбор по шагам
Создать собственный PDF и прочитать только первые восемь ASCII-символов заголовка. PDF ниже 1.5 отвергается до удаления вложений.
Добавить свой CSV и проверить наличие после закрытия записи.
Создать Массив имён с одной строкой guide-owned-book.csv. Передать его ЗаписатьУдалениеВложений, не КоллекцияВложенийPDF.
Закрыть писатель и повторно прочитать вложения. Сам PDF-файл остаётся для проверки.
Как проверить результат
До удаления собственное вложение одно, после удаления их 0: две булевые проверки дают Истина.
Удаляется ссылка на собственное вложение в PDF, а не весь файл. По выведенному пути свой PDF остаётся.
Ожидаемый результат
Удаление с точной границей владения и правильным типом аргумента.
На что обратить внимание
Поддержка удаления начинается с PDF 1.5. Проверка заголовка — условие этого упражнения, не полный валидатор PDF.
Удаление вложения не гарантирует безопасное физическое уничтожение его старых байтов при инкрементальной записи. Не используйте его как средство зачистки секретов.
Не формируйте список удаления из всех вложений чужого документа. В этом коде имя известно из собственного добавления.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.