При интеграции 1С с базой данных MS SQL Server для сохранения файлов часто используется конструкция OPENROWSET(BULK...). Однако при попытке сохранить файл, расположенный во временной папке сервера 1С, мы сталкиваемся с ошибкой исключительной ситуации 0x80040e14. Давайте разберемся, почему это происходит и как устранить данную проблему.
Основная причина кроется в архитектуре взаимодействия компонентов. Запрос, который мы отправляем через ADODB.Command, выполняется на стороне сервера базы данных (MS SQL Server), а не на сервере 1С. Когда вы указываете путь к файлу в методе OPENROWSET, SQL-сервер пытается найти этот файл на своем локальном диске или в доступной для него сетевой директории.
Если файл находится во временной папке сервера 1С (например, C:\Users\USR1CV8\AppData\Local\Temp\), то SQL-сервер просто не видит этот путь. Даже если путь кажется верным, у службы, под которой запущен SQL-сервер (часто это виртуальная учетная запись NT Service\MSSQLSERVER или специфический доменный пользователь), нет прав на доступ к профилю пользователя USR1CV8 на другом сервере.
Если вам необходимо передавать файлы через файловую систему, самый надежный способ — организовать общую сетевую папку. Разберем этот процесс по шагам:
UNC (например, \\ServerName\ShareName\File.pdf).Пример кода для записи файла в общую папку:
// Путь должен быть сетевым, а не локальным
ПутьКФайлу = "\\ServerName\SharedFolder\ИмяФайла.pdf";
ДД.Записать(ПутьКФайлу);
sqlЗапрос = "UPDATE [Files] SET [File] = (SELECT * FROM OPENROWSET(BULK '" + ПутьКФайлу + "', SINGLE_BLOB)) WHERE [ID] = '" + ID + "'";
// Далее выполнение команды через ADODB
Чтобы не зависеть от прав доступа к файловой системе и настройки сетевых папок, лучше всего отказаться от OPENROWSET в пользу передачи данных через параметры ADODB.Command. Этот метод позволяет передать содержимое файла прямо из памяти сервера 1С в базу данных MS SQL.
Рассмотрим, как реализовать такой подход:
ДвоичныеДанные.Command с типом данных adLongVarBinary.
// Создаем параметр для SQL
Parameter = Command.CreateParameter("@FileData", 205, 1, -1, ДвоичныеДанныеЗначение);
Command.Parameters.Append(Parameter);
// SQL запрос с использованием параметра
sqlЗапрос = "UPDATE [Files] SET [File] = ? WHERE [ID] = '" + ID + "'";
Command.CommandText = sqlЗапрос;
Command.Execute();
Такой подход считается наиболее профессиональным и безопасным, так как он исключает проблему «двойного прыжка» (double hop) аутентификации и не требует настройки прав на доступ к локальным папкам серверов.
Если вы все же решили использовать OPENROWSET, проанализируйте ситуацию с точки зрения безопасности:
LocalSystem или виртуальной записи, она не сможет обратиться к сетевым ресурсам (общим папкам). Рекомендуется использовать доменную учетную запись для службы SQL, если требуется доступ к сетевым ресурсам.BULK. Для этого часто требуется выполнение команды sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE;.Подводя итог: если ваша задача — быстрое решение, используйте сетевую папку с правильными правами доступа. Если же вы хотите построить надежную и масштабируемую систему — переходите на передачу двоичных данных через параметры SQL-запроса, минуя использование OPENROWSET.