В процессе разработки на платформе 1С часто возникает задача: есть данные в формате ДвоичныеДанные, и их нужно сохранить как физический файл на диск. Например, вы получили из базы данных или с веб-сервиса PDF-документ в виде двоичных данных и теперь хотите предоставить пользователю возможность его скачать. Давайте подробно разберемся, как это сделать правильно, какие могут возникнуть ошибки и как их избежать.
Основной вопрос, который возникает у разработчиков, связан с методом Записать() объекта ДвоичныеДанные. Что именно нужно передавать в качестве параметра и почему возникают ошибки вроде «файл не обнаружен» или «нет доступа»? Проанализируем эту задачу по шагам.
Для преобразования объекта ДвоичныеДанные в файл предназначен его собственный метод — Записать(ИмяФайла). Вся сложность заключается в правильном формировании параметра ИмяФайла.
Ключевое правило: в параметр ИмяФайла необходимо передавать полный путь к файлу, который включает в себя каталог, имя самого файла и его расширение. Просто указать "МойДокумент.pdf" недостаточно, система не поймет, куда именно его сохранять.
Посмотрим на простой пример. Предположим, у нас есть переменная МоиДвоичныеДанные, которая уже содержит двоичные данные PDF-файла.
// Предположим, переменная уже заполнена
// МоиДвоичныеДанные = ...;
// 1. Определяем полный путь для сохранения.
// Важно: каталог "C:\Temp\My1CFiles\" должен существовать на диске!
// Если его нет, система выдаст ошибку "Каталог не обнаружен".
ИмяФайлаДляСохранения = "C:\Temp\My1CFiles\Invoice_123.pdf";
// 2. Вызываем метод Записать()
МоиДвоичныеДанные.Записать(ИмяФайлаДляСохранения);
// 3. Сообщаем пользователю (опционально)
Сообщить("Файл успешно сохранен по пути: " + ИмяФайлаДляСохранения);
После выполнения этого кода на диске C: в папке `My1CFiles` появится файл `Invoice_123.pdf`. Обратиться к этому файлу в дальнейшем можно, используя ту же переменную ИмяФайлаДляСохранения, например, для запуска или прикрепления к письму.
Даже с правильным кодом можно столкнуться с ошибками. Как правило, они связаны с правами доступа или контекстом выполнения кода. Разберем самые распространенные из них.
1. Ошибка «Отказано в доступе» или «Нет доступа»
Эта ошибка означает, что у процесса 1С нет прав на запись в указанный вами каталог. Важно понимать, от имени какого пользователя запущен этот процесс.
&НаКлиенте): права проверяются для текущего пользователя Windows, который запустил 1С. Если он пытается сохранить файл в системную папку (например, `C:\Windows\`), он, скорее всего, получит отказ.&НаСервере): права проверяются для пользователя, от имени которого запущена служба сервера 1С:Предприятия (обычно это специальный пользователь `USR1CV8`). Этот пользователь по умолчанию имеет ограниченные права и может не иметь доступа к произвольным папкам на сервере, таким как `C:\МоиДокументы\`. Для сохранения файлов на сервере рекомендуется использовать либо временные папки, либо специально созданные каталоги с настроенными правами доступа для пользователя службы 1С — для этой задачи подойдет обработка автоматического сохранения присоединенных файлов на диск.Решение: Убедитесь, что целевой каталог доступен для записи пользователю, от имени которого выполняется код. Для серверных вызовов — проверьте права пользователя службы сервера 1С.
2. Ошибка «Файл не обнаружен» или «Каталог не тот»
Такая ошибка чаще всего возникает из-за двух причин:
Записать() выполняется на сервере, то файл будет создан на диске сервера 1С, а не на компьютере пользователя. Пользователь, соответственно, не найдет его на своем рабочем столе и будет считать, что ничего не сохранилось.Решение: Всегда проверяйте существование каталога перед записью. Четко осознавайте, где выполняется ваш код — на клиенте или на сервере, чтобы понимать, на какой машине искать созданный файл.
Часто файл нужно создать на сервере лишь на короткое время — например, чтобы сформировать, прикрепить к электронному письму и сразу удалить. Для таких целей идеально подходит механизм временных файлов. Платформа предоставляет удобную функцию для получения уникального имени файла во временном каталоге ОС.
Для этого используется функция ПолучитьИмяВременногоФайла().
&НаСервере
Процедура СохранитьДанныеВоВременныйФайл(ДвоичныеДанныеДокумента)
// Получаем уникальное имя для временного файла с расширением .pdf
// Платформа сама определит путь к системной временной папке
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("pdf");
// Пример результата: "C:\Users\USR1CV8\AppData\Local\Temp\v8_1A2B_3.tmp.pdf"
Попытка
ДвоичныеДанныеДокумента.Записать(ИмяВременногоФайла);
// Здесь можно выполнить дальнейшие действия с файлом,
// например, отправить его по почте.
// ... код отправки письма ...
Исключение
ОписаниеОшибки = ОписаниеОшибки();
ВызватьИсключение "Не удалось записать временный файл: " + ОписаниеОшибки;
КонецПопытки;
// ВАЖНО: После использования временный файл следует удалить,
// чтобы не занимать место на диске сервера.
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
// Можно записать в лог, что не удалось удалить временный файл
КонецПопытки;
КонецПроцедуры
Рассмотрим классический сценарий: пользователь нажимает кнопку, выбирает файл на своем компьютере, и этот файл должен быть сохранен в определенную папку на сервере. Прямой доступ с сервера к файловой системе клиента невозможен из соображений безопасности. Правильный механизм работы выглядит так:
Посмотрим на код, реализующий этот алгоритм.
&НаКлиенте
Процедура ЗагрузитьФайлНаСервер()
// Открываем стандартный диалог выбора файла
ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогВыбора.Заголовок = "Выберите файл для загрузки на сервер";
Если ДиалогВыбора.Выбрать() Тогда
ВыбранныйФайл = ДиалогВыбора.ПолноеИмяФайла;
ИмяФайла = ДиалогВыбора.ИмяФайла;
// Помещаем файл во временное хранилище, получаем его адрес
АдресХранилища = "";
// Последний параметр "Истина" означает, что будет показан индикатор прогресса
ПоместитьФайл(АдресХранилища, ВыбранныйФайл, , Истина);
Если НЕ ПустаяСтрока(АдресХранилища) Тогда
// Вызываем серверную процедуру и передаем ей адрес и имя файла
СохранитьФайлИзВременногоХранилищаНаСервере(АдресХранилища, ИмяФайла);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура СохранитьФайлИзВременногоХранилищаНаСервере(АдресХранилища, ИмяФайла)
// 1. Получаем двоичные данные из хранилища по адресу
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранилища);
// 2. Формируем полный путь для сохранения на сервере
// Папка "D:\1C_Attachments\" должна существовать и быть доступна для записи!
ПутьНаСервере = "D:\1C_Attachments\" + ИмяФайла;
// 3. Записываем файл
Попытка
ДвоичныеДанныеФайла.Записать(ПутьНаСервере);
Сообщить("Файл успешно загружен на сервер: " + ПутьНаСервере);
Исключение
Сообщить("Не удалось сохранить файл на сервере. " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Этот подход является стандартным и наиболее правильным для работы с файлами в клиент-серверной архитектуре 1С.
Чтобы успешно сохранить двоичные данные в файл, следуйте этим рекомендациям:
ДвоичныеДанные.Записать().&НаКлиенте сохраняет файл на машине пользователя, &НаСервере — на машине сервера.ПоместитьФайл и ПолучитьИзВременногоХранилища).