При переходе с современных версий платформы (8.2 и 8.3) на более старые, такие как 1С 8.1, разработчики часто сталкиваются с отсутствием привычных механизмов. Одним из таких «камней преткновения» является работа с файлами и временным хранилищем. В версиях 8.2/8.3 функция ПоместитьФайл автоматически открывает диалог выбора и отправляет данные по временному URL-адресу. В 1С 8.1 такого понятия, как «Временное хранилище» (URL вида e1cib/tempstorage/...), попросту не существует. Давайте разберем, как программно реализовать этот процесс, используя доступные инструменты старой платформы.
Для начала проанализируем ситуацию: почему старый код из 8.3 не будет работать в 8.1? Основная причина заключается в том, что управляемые формы и тонкий клиент появились только в 8.2. Платформа 8.1 работает преимущественно в режиме «Толстого клиента», где взаимодействие между клиентом и сервером происходит иначе. Здесь нет необходимости в промежуточном «веб-хранилище» для передачи файлов. Вместо этого используются объекты ДвоичныеДанные и ХранилищеЗначений. Для изучения особенностей передачи файлов в современных версиях платформы можно использовать руководство по работе с файлами в управляемых формах платформы 8.3.
Рассмотрим подробнее этапы, которые нам необходимо реализовать:
Выясним, как запустить диалог выбора файла. Поскольку глобальной функции ПоместитьФайл нет, мы должны использовать объект ДиалогВыбораФайла. Этот объект позволяет гибко настроить фильтры и заголовки окна.
Посмотрим на пример кода для инициализации диалога:
Режим = РежимДиалогаВыбораФайла.Открытие;
Диалог = Новый ДиалогВыбораФайла(Режим);
Диалог.ПолноеИмяФайла = "";
Диалог.Заголовок = "Выберите файл для прикрепления";
Диалог.МножественныйВыбор = Ложь;
Диалог.Фильтр = "Изображения (*.JPG;*.PNG)|*.JPG;*.PNG|Документы PDF (*.PDF)|*.PDF|Все файлы (*.*)|*.*";
Если Диалог.Выбрать() Тогда
ПутьКФайлу = Диалог.ПолноеИмяФайла;
// Далее следует обработка выбранного файла
КонецЕсли;
В этом фрагменте мы создаем объект ДиалогВыбораФайла, устанавливаем фильтры для нужных нам расширений (например, картинок или PDF) и проверяем результат метода Выбрать(). Если пользователь нажал «Открыть», мы получаем строковую переменную с полным путем к файлу.
Зачастую после выбора файла нам нужно извлечь его имя или проверить расширение. В обсуждениях на форумах часто предлагают использовать строковые функции для разбора пути, однако мы рекомендуем использовать встроенный объект Файл. Это более надежный способ, так как он корректно обрабатывает системные разделители.
Проанализируем пример проверки расширения:
ВыбранныйФайл = Новый Файл(ПутьКФайлу);
ИмяФайла = ВыбранныйФайл.Имя;
Расширение = ВРег(ВыбранныйФайл.Расширение);
Если НЕ (Расширение = ".JPG" ИЛИ Расширение = ".PDF" ИЛИ Расширение = ".PNG" ИЛИ Расширение = ".TIF") Тогда
Предупреждение("Выбран недопустимый формат файла!");
Возврат;
КонецЕсли;
Использование объекта Файл позволяет нам не заботиться о том, стоят ли в пути символы "/" или "\". Метод Расширение вернет строку с точкой (например, ".pdf"), которую мы приводим к верхнему регистру для удобства сравнения.
Теперь перейдем к самому важному: как «поместить» файл, если нет функции ПоместитьВоВременноеХранилище? В 1С 8.1 для хранения произвольных данных в базе или передачи их между модулями используется объект ХранилищеЗначений — для этой задачи есть управление присоединенными файлами и их хранением.
Важный нюанс: если вы просто напишете Новый ХранилищеЗначений(ПутьКФайлу), система сохранит в объекте строку пути, а не содержимое файла. Чтобы сохранить сам файл, его нужно сначала прочитать в двоичном виде.
Разберем правильную последовательность действий:
// 1. Читаем файл с диска в память
ДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
// 2. Помещаем двоичные данные в ХранилищеЗначений
// Можно использовать сжатие (от 0 до 9), чтобы сэкономить место в базе
АрхивныйФайл = Новый ХранилищеЗначений(ДанныеФайла, Новый СжатиеДанных(9));
// 3. Записываем в реквизит документа или справочника
// Предположим, у нас есть реквизит "ДанныеФайла" с типом ХранилищеЗначения
Объект.ДанныеФайла = АрхивныйФайл;
Объект.ИмяФайла = ИмяФайла; // Сохраняем имя отдельно, так как ХЗ его не хранит
Соберем все части воедино. Представим, что мы пишем процедуру для кнопки «Прикрепить файл» на форме документа в 1С 8.1.
Процедура ОсновныеДействияФормыПрикрепитьФайл(Кнопка)
// Инициализация диалога
Режим = РежимДиалогаВыбораФайла.Открытие;
Диалог = Новый ДиалогВыбораФайла(Режим);
Диалог.Заголовок = "Выберите файл";
Если НЕ Диалог.Выбрать() Тогда
Возврат;
КонецЕсли;
ПутьКФайлу = Диалог.ПолноеИмяФайла;
ОбъектФайл = Новый Файл(ПутьКФайлу);
// Проверка размера (например, не более 5 Мб)
Если ОбъектФайл.Размер() > 5242880 Тогда
Сообщить("Файл слишком большой!");
Возврат;
КонецЕсли;
Попытка
// Чтение данных
ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
// Эмуляция помещения во "временное хранилище"
// В 8.1 мы просто сохраняем это в переменную или реквизит формы
Хранилище = Новый ХранилищеЗначений(ДвоичныеДанные, Новый СжатиеДанных(7));
// Заполнение реквизитов объекта
ДанныеФайла = Хранилище;
ИмяФайла = ОбъектФайл.Имя;
Сообщить("Файл успешно загружен: " + ИмяФайла);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Разберем обратную задачу. В 8.3 вы бы использовали ПолучитьФайл. В 8.1 процесс выглядит следующим образом: мы получаем данные из ХранилищеЗначений, извлекаем из них ДвоичныеДанные и записываем их на диск во временную папку пользователя.
// Получаем двоичные данные из реквизита
ДанныеДляЗаписи = ДанныеФайла.Получить();
Если ТипЗнч(ДанныеДляЗаписи) = Тип("ДвоичныеДанные") Тогда
// Формируем путь во временном каталоге
ВременныйПуть = КаталогВременныхФайлов() + ИмяФайла;
// Записываем физически на диск
ДанныеДляЗаписи.Записать(ВременныйПуть);
// Открываем файл средствами ОС
ЗапуститьПриложение(ВременныйПуть);
КонецЕсли;
Мы выяснили, что прямой замены функции ПоместитьФайл одной строчкой в 1С 8.1 нет. Однако, комбинируя ДиалогВыбораФайла, ДвоичныеДанные и ХранилищеЗначений, можно добиться полной идентичности бизнес-логики.
Основные советы при работе в 8.1:
ОбъектФайл.Существует().ХранилищеЗначений не хранит имя и расширение файла автоматически — создавайте для этого дополнительные строковые реквизиты в базе данных.Новый ДвоичныеДанные(Путь) должно происходить на клиенте, так как сервер не имеет доступа к локальным дискам пользователя. Полученный объект ДвоичныеДанные затем передается на сервер для записи в базу.КаталогВременныхФайлов() для корректного определения путей сохранения временных данных, чтобы не возникало проблем с правами доступа в Windows.Проанализировав эти подходы, вы сможете успешно перенести механизмы прикрепления файлов из современных конфигураций УПП или ERP в старые системы на базе 1С 8.1.