Передача файлов с сервера на клиент
Доброго времени суток!
Только начинаю программировать, прошу пожалуйста подсказать в решении проблемы:
Перенос обработки с обычных на УФ,
При выполнении, выдает ошибку:
«Ошибка при выполнении файловой операции D:\Файлы\ПримерВыгрузки\Выгрузка данных водителя 00856 от 05072021-05072021.xls»
Данная ошибка выходит по причине того что запись Табличного документа в файл Excel происходит на сервере, а не на клиенте. у серверной машины нет доступа к ПК клиента(Расшарить папку для сервера нет возможности, так как пользователи работают в домене, а сервер находится не домене).
Возможно как то можно реализовывать через механизм временного хранилища(ПоместитьВоВременноеХранилище(),ПолучитьИзВременногоХранилища()) и двоичные данные, только не знаю как это сделать:(
Примечания по коду:
//представленный код процедуры выполняется на сервере
//переменная Каталог, указывается путь к папке на форме
Результат = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); ТабДок = Новый ТабличныйДокумент; ОбъектОбработки = РеквизитФормыВЗначение("Объект"); Макет = ОбъектОбработки.ПолучитьМакет("МакетВыгрузки"); ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ОбластьШапка"); ТабДок.Очистить(); ТабДок.Вывести(ОбластьШапкаТаблицы); Нач = Строка(Формат(НачалоПериода,"ДФ=дд"))+Строка(Формат(НачалоПериода,"ДФ=ММ"))+Строка(Формат(НачалоПериода,"ДФ=гггг")); Кон = Строка(Формат(ОкончаниеПериода,"ДФ=дд"))+Строка(Формат(ОкончаниеПериода,"ДФ=ММ"))+Строка(Формат(ОкончаниеПериода,"ДФ=гггг")); КолСотрудников = 0; Пока Результат.Следующий() Цикл КолСотрудников = КолСотрудников+1; ТабДокВодитель = Новый ТабличныйДокумент; ТабДокВодитель.Очистить(); ТабДокВодитель.Вывести(ОбластьШапкаТаблицы); Стр = Результат.Выбрать(); Пока Стр.Следующий() Цикл ОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("ОбластьДанные"); ОбластьДетальныхЗаписей.Параметры.Заполнить(Стр); ТабДокВодитель.Вывести(ОбластьДетальныхЗаписей); ТабДок.Вывести(ОбластьДетальныхЗаписей); КонецЦикла; Путь = ?(Лев(Каталог,СтрДлина(Каталог)-1)="\",Каталог,Каталог+"\")+"Выгрузка данных водителя "+Строка(Результат.Водитель)+" от "+Нач+"-"+Кон+".xls"; ТабДокВодитель.Вывод=ИспользованиеВывода.Разрешить; ТабДокВодитель.Записать(Путь, ТипФайлаТабличногоДокумента.XLS97); КонецЦикла; ВремКаталог = Каталог; СоздатьКаталог(ВремКаталог); Путь = ?(Лев(Каталог,СтрДлина(Каталог)-1)="\",Каталог,Каталог+"\")+"Выгрузка данных водителей "+Нач+"-"+Кон+".xls"; ТабДок.Вывод=ИспользованиеВывода.Разрешить; Если КолСотрудников>1 Тогда ТабДок.Записать(Путь, ТипФайлаТабличногоДокумента.XLS97); КонецЕсли;
По теме из базы знаний
- Как передать документ Word (ActiveDocument или ДвоичныеДанные) с сервера на клиент
- Передача файла с клиента на сервер и с сервера на клиент. Управляемые формы
- Работа с файлами в управляемых формах клиент серверной версии 8.3 и выше
- Динамические реквизиты на управляемой форме и передача файла Excel на сервер
- Передача данных с сервера на клиент
- Дата
- Дата
- Рейтинг всех уровней
- Рейтинг 1-го уровня
- Древо развёрнутое
- Древо свернутое
Свернуть все
2. Alexei_Siva 145 02.09.21 09:40 Сейчас в теме
Добрый день, нужно записывать временный файл на сервере, помещать его во временное хранилище и передавать на клиент. Так, например, делается в обработке «Универсальный обмен данными в формате XML»
4. Alexei_Siva 145 02.09.21 09:48 Сейчас в теме
(2)Вот пример, если поможет
&НаСервере Функция ВыгрузитьНаСервере() . АдресФайлаДанных = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ВремИмяФайла), УникальныйИдентификатор); УдалитьФайлы(ВремИмяФайла); Возврат АдресФайлаДанных; КонецФункции
&НаКлиенте Процедура Выгрузить(Команда) АдресФайлаДанныхВХранилище = ВыгрузитьНаСервере(); ДвДанные = ПолучитьИзВременногоХранилища(АдресФайлаДанныхВХранилище); //, ВремИмяФайла ДвДанные.Записать(ИмяФайла); КонецПроцедуры
user1536836; + 1 – Ответить
3. Азбука Морзе 103 02.09.21 09:45 Сейчас в теме
Самое простое — сделать реквизит формы типа Табличный документ, который будет доступен как на клиенте так и на сервере и через него осуществлять обмен.
5. user1536836 02.09.21 09:53 Сейчас в теме
(3)Тоже об этом думал, но в цикле могут формироваться несколько табличных документов, что думаю усложнит задачу.
6. Азбука Морзе 103 02.09.21 10:02 Сейчас в теме
(5) усложнит конечно, но проблемы решаются))
7. user1536836 02.09.21 14:17 Сейчас в теме
В общем разобрался, через механизм временного хранилища,
На форме создал 3 реквизита для временных хранилищ с типом «строка», и 3 реквизита уникальных идентификатора с типом «уникальный идентификатор»;
&НаКлиенте ПолучитьДанныеДляВыгрузкиНаСервере(); МассивДанныхВодитлей = ПолучитьИзВременногоХранилища(АдресХранилищаТабДокументов); МассивНаименований = ПолучитьИзВременногоХранилища(АдресХранилищаНаименованийДокументов); Каталог = Объект.Каталог; Путь = ?(Лев(Каталог,СтрДлина(Каталог)-1)="\",Каталог,Каталог+"\"); Индекс = 0; Для каждого ТабДокумент Из МассивДанныхВодитлей Цикл Путь = МассивНаименований.Получить(Индекс); Индекс = Индекс+1; ТабДокумент.Вывод=ИспользованиеВывода.Разрешить; ТабДокумент.Записать(Путь, ТипФайлаТабличногоДокумента.XLS97); КонецЦикла; Если МассивДанныхВодитлей.Количество() > 1 Тогда НачалоПериода = Объект.НачалоПериода; ОкончаниеПериода = Объект.ОкончаниеПериода; Нач = Строка(Формат(НачалоПериода,"ДФ=дд"))+Строка(Формат(НачалоПериода,"ДФ=ММ"))+Строка(Формат(НачалоПериода,"ДФ=гггг")); Кон = Строка(Формат(ОкончаниеПериода,"ДФ=дд"))+Строка(Формат(ОкончаниеПериода,"ДФ=ММ"))+Строка(Формат(ОкончаниеПериода,"ДФ=гггг")); ТабДок = ПолучитьИзВременногоХранилища(АдресПутиОбщейВыгрузки); ВремКаталог = Каталог; СоздатьКаталог(ВремКаталог); Путь = ?(Лев(Каталог,СтрДлина(Каталог)-1)="\",Каталог,Каталог+"\")+"Выгрузка данных водителей "+Нач+"-"+Кон+".xls"; ТабДок.Вывод=ИспользованиеВывода.Разрешить; ТабДок.Записать(Путь, ТипФайлаТабличногоДокумента.XLS97); КонецЕсли; КонецПроцедуры &НаСервере Процедура ПолучитьДанныеДляВыгрузкиНаСервере() Запрос = Новый Запрос; Запрос.Текст = ". "; Запрос.Параметры(. ); Результат = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); ТабДок = Новый ТабличныйДокумент; ОбъектОбработки = РеквизитФормыВЗначение("Объект"); Макет = ОбъектОбработки.ПолучитьМакет("МакетВыгрузки"); ОбластьШапкаТаблицы = Макет.ПолучитьОбласть("ОбластьШапка"); ТабДок.Очистить(); ТабДок.Вывести(ОбластьШапкаТаблицы); Нач = Строка(Формат(НачалоПериода,"ДФ=дд"))+Строка(Формат(НачалоПериода,"ДФ=ММ"))+Строка(Формат(НачалоПериода,"ДФ=гггг")); Кон = Строка(Формат(ОкончаниеПериода,"ДФ=дд"))+Строка(Формат(ОкончаниеПериода,"ДФ=ММ"))+Строка(Формат(ОкончаниеПериода,"ДФ=гггг")); КолСотрудников = 0; МассивФайлов = Новый Массив; МассивНаименованийФайлов = Новый Массив; Пока Результат.Следующий() Цикл КолСотрудников = КолСотрудников+1; ТабДокВодитель = Новый ТабличныйДокумент; ТабДокВодитель.Очистить(); ТабДокВодитель.Вывести(ОбластьШапкаТаблицы); Стр = Результат.Выбрать(); Пока Стр.Следующий() Цикл ОбластьДетальныхЗаписей = Макет.ПолучитьОбласть("ОбластьДанные"); ОбластьДетальныхЗаписей.Параметры.Заполнить(Стр); ТабДокВодитель.Вывести(ОбластьДетальныхЗаписей); ТабДок.Вывести(ОбластьДетальныхЗаписей); КонецЦикла; Путь = ?(Лев(Каталог,СтрДлина(Каталог)-1)="\",Каталог,Каталог+"\")+"Выгрузка данных водителя "+Строка(Результат.Водитель)+" от "+Нач+"-"+Кон+".xls"; ИмяФайла = "Выгрузка данных водителя "+Строка(Результат.Водитель)+" от "+Нач+"-"+Кон+".xls"; //Сохраняем ТабДокументы и пути их сохранения в массивы МассивФайлов.Добавить(ТабДокВодитель); МассивНаименованийФайлов.Добавить(Путь); КонецЦикла; //Помещаем массивы чтобы получить их позже на клиенте ЭтаФорма.АдресХранилищаТабДокументов = ПоместитьВоВременноеХранилище((МассивФайлов), ЭтаФорма.УникальныйИдентификаторФайлов); ЭтаФорма.АдресХранилищаНаименованийДокументов = ПоместитьВоВременноеХранилище((МассивНаименованийФайлов), ЭтаФорма.УникальныйИдентификаторНаименований); Если КолСотрудников>1 Тогда //сохраняем ТабДокумент с водителями во врем.хранилище чтобы позже получить его на клиенте ЭтаФорма.АдресПутиОбщейВыгрузки = ПоместитьВоВременноеХранилище(ТабДок, ЭтаФорма.УникальныйИдентификаторОбщейВыгрузки); КонецЕсли; КонецПроцедуры
Пример получения файла с сервера
Иногда, но появляется необходимость получить быстрый способ переноса содержимого файла с удаленного сервера к себе на локальный компьютер, для его последующего открытия и просмотра. В связи с чем предлагаю вашему вниманию обработку для рассмотрения и возможной реализации.
Скачать файлы
Не нашел оптимального варианта решения данной обработки (или плохо искал), в связи с чем сделал свою, которая может производить перенос содержимого файла (при желании файлов).
Для начала есть представление о том, что у пользователя, работающего на «тонком» клиенте, не всегда есть возможность видеть, что происходит в серверной части программы, но просмотреть или прочитать полученные данные, хранящихся в файлах, которые создаются другими, будь то пользователями или внешними службами, ему крайне необходимо.
Для решения данной ситуации было предпринято много вариантов решения, один из них указан в этой небольшой публикации.
На стороне клиента
//Получаем содержимое файла с сервера по адресу Адрес = ПолучениеФайлаОбращениеКСерверу(); // как пример -> C:\pricexls1\price1.xlsx" Описание = Новый ОписаниеПередаваемогоФайла("C:\pricexls1\price1.xlsx",Адрес); МассивОписаний=Новый Массив; МассивОписаний.Добавить(Описание); ПолучитьФайлы(МассивОписаний. Ложь);
На стороне сервера
// Проверка на существование каталога для файла выгрузки // Для примера указан -> G:\pricexls1\ КаталогККМ = "G:\pricexls1\"; КаталогНаДиске = Новый Файл(КаталогККМ); Если Не КаталогНаДиске.Существует() Тогда СоздатьКаталог(КаталогККМ); КонецЕсли; ПолноеИмяФайла = КаталогККМ + "price1.xlsx"; ПолноеИмяФайла = Новый Файл(ПолноеИмяФайла); // Получение данных Возврат ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ПолноеИмяФайла.ПолноеИмя), ЭтаФорма.УникальныйИдентификатор);
В обработке находится исходный текст, на примере которого можно сформировать выгрузку данных файла с удаленного сервера.
- Обработка сформирована на управляемой форме конфигурации «1С:Управление Торговлей 11.1», выполнение выгрузки производилась на ее примере.
- Также данная обработка может пригодиться программистам, работающими независимо от типа конфигураций с управляемыми формами. В обработке в качестве примера указан статичный каталог который может изменяться по требованию (интерактивный выбора каталога не реализован), но в тоже время наименовании адрес каталога хранения фалов может быть изменен непосредственно под ваши задачи.
- Все тесты и запуск внешней обработки производилась на конфигурации 1С:Управление Торговлей 11.1 платформы 1С:Предприятие 8.3 (8.3.5.1428).
Это внешняя обработка, компоненты для нее не нужны, обработка использует типовые механизмы конфигурации Управление торговлей 11.1(2.3) платформы 1С:Предприятие 8.2 и/или 8.3
- Минимальный релиз платформы. Управление торговлей релиз 11.1.
- Режим использования синхронных вызовов — Использовать с предупреждениями
- Режим совместимости интерфейса — Версия 8.2. Разрешить Такси
Каталог статей
1) сначала открываем диалог выбора файла немодально и присваиваем реквизиту формы ФайлДанных значение выбранного файла. Для строкового реквизита ФайлДанных устанавливаем свойство «Кнопка выбора» = Да, и пишем обработчик события «Начало выбора».
2) передаем файл на сервер после чего обрабатываем его. (можно почитать здесь: https://its.1c.ru/db/v8std#content:542:hdoc)
Для передачи используем процедуру НачатьПомещениеФайла(ОписаниеОповещения, , ФайлДанных, Ложь, УникальныйИдентификатор);.
Здесь УникальныйИдентификатор — это УИД формы (можно было написать ЭтаФорма.УникальныйИдентификатор)
На входе процедуры в описании оповещения вторым параметром идет Адрес. Его можно задать принудительно при вызове процедуры НачатьПомещениеФайла. Если он не задан, то создается новый файл и в адрес будет занесен путь файла во временном хранилище. У этой процедуры есть параметр «Интерактивно» (в примере ниже он равен Ложь). Если он равен Истина, то можно не писать обработку выбора файла. Система сама вызовет такой диалог и передаст файл во временное хранилище.
С платформы 8.3.15 рекомендуется использовать метод НачатьПомещениеФайлаНаСервер(). Пример использования данного метода можно посмотреть здесь.
1С сильно рекомендует использовать ПолучитьИмяВременногоФайла() для создания временных файлов. При этом имя формируется в временный каталог пользователя. сли имя временного файла и каталог задать жестко, то есть вероятность того, то при запуске обработки другим пользователем выйдет ошибка совместного доступа к файлу.
&НаКлиенте
Процедура ФайлДанныхНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = «»;
Фильтр = «*.csv|**.csv»;
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = «Выберите файл»;
Оповещение = Новый ОписаниеОповещения(«ОбработкаОткрытияФайла», ЭтотОбъект, Новый Структура(«Диалог», ДиалогОткрытияФайла));
ДиалогОткрытияФайла.Показать(Оповещение);
КонецПроцедуры
Файл = Новый Файл(ФайлДанных);
Если Не Файл.Существует() Тогда
Сообщить(«Файл не найден! Выберите файл заново.»);
Возврат;
КонецЕсли;
Файл =Неопределено;
ОписаниеОповещения = Новый ОписаниеОповещения(«ОбработатьФайлЗавершение», ЭтотОбъект);
НачатьПомещениеФайла(ОписаниеОповещения,
,
ФайлДанных,
Ложь,
УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Функция ПроизвестиОбработкуНаСервере(Адрес)
Результат = «»;
ПОпытка
Данные = ПолучитьИзВременногоХранилища(Адрес);
ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла(«csv»);
Данные.Записать(ИмяПромежуточногоФайла);
ДанныеФайла = Новый ЧтениеТекста(ИмяПромежуточногоФайла);
СТрокаФайла = ДанныеФайла.ПрочитатьСтроку();
Пока СтрокаФайла <> Неопределено Цикл
//обработка строк
СтрокаФайла = ДанныеФайла.ПрочитатьСтроку();
КонецЦикла;
Исключение
Результат = ОписаниеОшибки();
КонецПопытки;
Организация хранилища файлов внутри базы данных 1C+MS-SQL
Довольно часто в различных вариантах учетных задач возникает проблема размещения различной информации (файлов) с привязкой их к базе данных. Например, построение на базе 1С системы учета документооборота с хранением файлов в формате Word , Excel . Если организовывать такое хранилище в виде каталогов файлов, то очень велика вероятность нарушения работы системы в результате ряда факторов, вызванных, как правило, неумелыми, либо наоборот, «слишком умелыми» действиями пользователя. Другими словами система хранения файлов в каталоге базы 1С , ввиду своей общедоступности является существенной прорехой в безопасности. Файлы легко переименовать, перезаписать, испортить или удалить.
Таким образом, мы постепенно подходим к мысли хранения файлов непосредственно в базе данных MS SQL . Остается вопрос, каким образом всё это можно организовать? В своей статье, я постараюсь дать как можно более подробный ответ на этот вопрос. Все исследования будут происходить на платформе MS SQL 2000 , далее просто SQL .
Итак, первый вопрос на повестке дня – создание таблицы для хранения файлов. Как известно, SQL позволяет создавать таблицы, содержащие поля с типом IMAGE (в переводе на русский «образ»). В поле такого типа мы и будем хранить свой файл. Для обеспечения уникальности данных и возможности в дальнейшем получения доступа к файлу нам необходимо создать колонку с типом int , которая у нас будет иметь свойство « Identity ». Это свойство обеспечит нам автоматическую нумерацию строк таблицы средствами SQL . Первоначальный номер у нас будет выставлен в « 1 », приращение номера будет тоже идти по « 1 ».
Второй вопрос на повестке дня, – в какой базе создавать таблицу? Требуется ли для ее хранения отдельная база данных, или можно воспользоваться уже существующей базой данной 1С . Как показали опыты, 1С при операциях, затрагивающих базу данных, таких как выгрузка, загрузка, реструктуризация, работает только со «своими» таблицами не затрагивая те, которые отсутствуют в ее файле DDS . Это дает нам возможность поместить нашу таблицу непосредственно в базе данных 1С . При этом, однако, следует иметь в виду, что раз 1С не трогает «не свои» таблицы, то при выгрузке данных наша таблица выгружаться не будет. Поэтому, для обеспечения резервного копирования или переноса данных придется использовать средства SQL . С другой стороны, если мы помещаем нашу таблицу в отдельную базу данных, то получаем более гибкие возможности работы, в частности легче можно будет наладить репликацию данной таблицы, что немаловажно. В моем примере таблица будет расположена непосредственно в базе данных 1С .
Теперь нам остается создать необходимый скрипт. Сразу определимся, что работать с хранимыми в базе данных файлами мы будем с использованием технологии ADO . Отсюда вытекает необходимость работы в нормальном рабочем режиме только в разделенном режиме работы 1С -Предприятия, так как в монопольном соединение ADO не сможет получить доступ к базе данных.
Сделаем так, чтобы процедура проверки наличия необходимой таблицы в базе данных запускалась в из процедуры ПриНачалеРаботыСистемы () когда режим работы пользователя разделенный. Текст процедуры можно посмотреть здесь.
Теперь у нас есть в базе необходимая таблица. Следующая задача — научиться записывать в нее необходимые данные. Для этого мы воспользуемся такой возможностью SQL-сервера , как « BULK » операции. Это операции манипулирования большими объемами данных, точнее сказать это операции обмена данными между SQL-сервером и файлом определенной структуры, который может содержать как одну строку данных для SQL-сервера , так и большое их количество. Определение структуры данных, содержащихся в файле, происходит с помощью специального файла-формы.
Итак, мы определлись, что будем записывать файл в базу данных с помощью операции « BULK INSERT ». В процедуре записи файла в базу данных, мы должны выполнить следующие действия:
- получить последний номер строки и сохранить его в переменной;
- создать и заполнить содержимым файл формы;
- выполнить архивацию исходного файла для уменьшения его объема на сервере (не обязательно — у меня делается ввиду большого объема данных);
- создать файл исходных данных;
- выполнить запрос на размещение на сервере;
- получить последний номер строки и сравнить его с сохраненным ранее значением;
- если номер увеличился на «1» — значит операция прошла успешно, иначе — была ошибка.
Важное примечание: так как результирующий запрос будет выполнять сервер, необходимо, чтобы файлы, используемые сервером были доступны для него. Соответственно, при формировании путей к файлам мы должны «смотреть на них» со стороны сервера. То есть, получив запрос на размещение файла «C:myfile.doc» сервер будет искать его именно на своем диске, а не на компьютере-клиенте. Лучше всего сохранять файлы в сетевых папках доступных серверу и сразу указывать сетевые пути .
Текст процедуры глобального модуля осуществляющей размещение файла в таблице базы данных SQL можно посмотреть здесь.
Следующий вопрос, который нам предстоит решить — каким образом можно извлечь файл из базы данных. Тут дело обстоит сложнее. Придется воспользоваться утилитой BCP , входящей в состав поставки MS SQL сервера . Эта утилита служит для пакетного обмена данными с SQL сервером . В принципе, мы могли бы воспользоваться этой утилитой и для загрузки файла на сервер, но, думается, что, чем меньше будет мелькать дополнительных окошек, тем лучше. Принцип использования утилиты такой же как у команды « BULK INSERT », с тем различием, что нам нужно получить данные с сервера, а не загрузить на него.
Таки образом список действий, который нам надо выполнить становится намного короче:
- создать файл формы;
- выполнить утилиту BCP с параметрами;
- разархивировать полученный файл (если использовалось архивирование).
Функцию глобального модуля, служащую для извлечения файла с сервера можно посмотреть здесь.

