Как получить файл из справочника и отправить его по электронной почте в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки в среде 1С часто возникает задача автоматизации почтовых рассылок, к которым необходимо прикрепить файлы, хранящиеся внутри информационной базы. На первый взгляд задача кажется простой, однако начинающие разработчики часто сталкиваются с техническими трудностями: от ошибок при работе с временным хранилищем до проблем с получением данных, если файлы хранятся не в самой базе, а в томах на диске. В этой статье мы подробно разберем, как правильно извлечь файл из справочника и корректно отправить его адресату.

Разбор типичных ошибок при получении файла

Рассмотрим ситуацию, с которой столкнулся автор темы. Первая попытка получить файл заключалась в поиске элемента справочника и попытке поместить весь объект СправочникОбъект.Файлы во временное хранилище. Это привело к ошибке: "Переданное значение не может быть помещено во временное хранилище". Проанализируем причину: во временное хранилище нельзя помещать объекты данных (такие как ссылки или объекты справочников в чистом виде) для передачи их между клиентом и сервером в таком контексте, если система ожидает именно поток данных.

Важно понимать разницу между метаданными (карточкой файла в справочнике) и самим содержимым файла. Содержимое файла в 1С обычно хранится в реквизите с типом ХранилищеЗначения. Однако просто получить этот реквизит недостаточно — данные из него нужно извлечь методом Получить().

Способ 1. Ручное извлечение данных из Хранилища Значения

Если ваша конфигурация не использует Библиотеку стандартных подсистем (БСП) и файлы хранятся непосредственно в реквизите справочника, мы можем применить следующий алгоритм. Разберем его по шагам:

  1. Найдем ссылку на элемент справочника.
  2. Обратимся к реквизиту, содержащему файл (например, ФайлХранилище).
  3. Извлечем ДвоичныеДанные из хранилища.
  4. Поместим их во временное хранилище для передачи на клиент или используем сразу на сервере.

Посмотрим на пример кода, который реализует эту логику:


&НаСервере
Функция ПолучитьАдресФайлаНаСервере(ИмяФайла)
    // Поиск элемента справочника по наименованию
    ЭлементСправочника = Справочники.Файлы.НайтиПоНаименованию(ИмяФайла);
    
    Если ЭлементСправочника.Пустая() Тогда
        Возврат Неопределено;
    КонецЕсли;

    // Извлечение данных из реквизита ХранилищеЗначения
    // Реквизит ФайлХранилище содержит объект типа ХранилищеЗначения
    ДвоичныеДанные = ЭлементСправочника.ФайлХранилище.Получить();
    
    Если ТипЗнч(ДвоичныеДанные) <> Тип("ДвоичныеДанные") Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    // Помещаем данные во временное хранилище, чтобы клиент мог их скачать или отправить
    Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтаФорма.УникальныйИдентификатор);
    
    Возврат Адрес;
КонецФункции

Этот метод рабочий, но у него есть существенный недостаток: он не учитывает современные стандарты хранения файлов в 1С (БСП), где файлы могут находиться в томах на сервере (вне базы данных).

Способ 2. Использование механизмов БСП (Рекомендуемый)

Если вы работаете в современных конфигурациях (таких как ERP, УТ 11, БП 3.0), настоятельно рекомендуется использовать программный интерфейс библиотеки стандартных подсистем. Проанализируем, почему это лучше: методы БСП автоматически проверяют, где физически лежит файл (в базе или в томе на диске), проверяют права доступа пользователя и корректно обрабатывают расширения файлов.

Для решения нашей задачи идеально подходит общий модуль РаботаСФайлами. Рассмотрим итоговый вариант кода, который оказался успешным у автора темы:


&НаСервере
Функция ПолучитьДвоичныеДанныеФайла(СсылкаНаФайл)
    // Используем стандартный метод БСП для получения данных
    // Он вернет объект типа ДвоичныеДанные независимо от способа хранения
    Попытка
        ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл);
        Возврат ДвоичныеДанные;
    Исключение
        ЗаписьЖурналаРегистрации("ОтправкаПочты", УровеньЖурналаРегистрации.Ошибка, , , 
            "Не удалось получить данные файла: " + ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
КонецФункции

Стоит отметить, что в более свежих версиях БСП рекомендуется использовать метод ПрисоединенныеФайлы.ПолучитьДанныеФайла(СсылкаНаФайл), так как он является более универсальным для подсистемы присоединенных файлов.

Формирование электронного письма с вложением

Теперь, когда мы научились получать двоичные данные файла, выясним, как правильно прикрепить их к письму. Процесс создания письма обычно происходит на стороне сервера, так как именно там настроены учетные записи почты и системные параметры.

Разберем ситуацию: часто разработчики совершают ошибку, передавая в метод Добавить() вложений просто двоичные данные без указания имени файла. В этом случае получатель может получить файл с непонятным названием вроде "noname.bin". Чтобы этого избежать, всегда нужно указывать имя файла с его расширением.

Проанализируем пример кода для отправки письма с вложением:


&НаСервере
Процедура ОтправитьПисьмоСФайлом(СсылкаНаФайл, АдресПолучателя)
    
    // 1. Получаем данные и имя файла
    ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл);
    ИмяФайлаСРасширением = СсылкаНаФайл.Наименование + "." + СсылкаНаФайл.Расширение;
    
    // 2. Создаем объект сообщения
    Письмо = Новый ИнтернетПочтовоеСообщение;
    Письмо.Тема = "Вам отправлен файл из 1С";
    Письмо.Получатели.Добавить(АдресПолучателя);
    Письмо.Тексты.Добавить("Добрый день! Во вложении находится запрашиваемый файл.", ТипТекстаПочтовогоСообщения.ПростойТекст);
    
    // 3. Добавляем вложение
    // Важно: вторым параметром передаем имя файла, которое увидит пользователь
    Письмо.Вложения.Добавить(ДвоичныеДанные, ИмяФайлаСРасширением);
    
    // 4. Отправка через системную учетную запись
    // Предполагается, что УчетнаяЗапись уже настроена в системе
    УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("ОсновнаяПочта");
    
    Почта = Новый ИнтернетПочта;
    Попытка
        Почта.Подключиться(РаботаСПочтовымиСообщениями.ПараметрыПодключения(УчетнаяЗапись));
        Почта.Послать(Письмо);
        Почта.Отключиться();
        Сообщить("Письмо успешно отправлено!");
    Исключение
        Сообщить("Ошибка при отправке: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Оптимизация работы с большими файлами

Рассмотрим важный нюанс: передача файлов через ДвоичныеДанные напрямую в оперативную память может быть накладной для сервера, если файлы весят десятки или сотни мегабайт. Если вы планируете работать с тяжелыми вложениями, проанализируем альтернативный путь — использование временных файлов на диске.

Вместо хранения данных в оперативной памяти (в переменной типа ДвоичныеДанные), мы можем записать файл во временную директорию сервера:

  1. Используем ПолучитьИмяВременногоФайла() для генерации пути.
  2. Записываем данные на диск методом ДвоичныеДанные.Записать().
  3. Добавляем вложение в письмо, указывая путь к файлу на диске.
  4. После отправки обязательно удаляем временный файл, чтобы не переполнять дисковое пространство сервера.

Такой подход гарантирует стабильную работу системы даже при одновременной отправке множества тяжелых документов несколькими пользователями.

Подведем итоги

Для успешного получения файла из справочника и его отправки почтой необходимо:

Следуя этим рекомендациям, вы сможете создать надежный механизм обмена файлами в ваших решениях на платформе 1С:Предприятие.

← На главную