ООО ЭкоЮнит
FAQSearchMemberlistUsergroupsFilesLog inRegisterГлавная
printer-friendly view
 
 
AuthorMessage
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

 !  Sergey @ Wed 22 Jan, 2014 20:37:
Редакция статьи, переработанной с учетом замечаний, приобретённого опыта, а также с учетом изменений в платформе 8.3.


В статье собран мой опыт по передаче данных на веб-сервер.

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

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

Для передачи данных на сервер методом POST в 1С: Предприятии 8.X применяется метод HTTPСоединение.ОтправитьДляОбработки()
По файлу-источнику и адресу ресурса:
Code:
ОтправитьДляОбработки(<Источник>, <Адрес ресурса>, <Имя выходного файла>, <ЗаголовкиHTTP>);


Для 1С: Предприятия 8.3 и платформы 8.2.18 и позднее может использоваться синтаксис по HTTP-запросу, позволяющий отказаться от формирования временных файлов отправки и ответа сервера:
Code:
ОтправитьДляОбработки(<HTTPЗапрос>, <ИмяВыходногоФайла>);

(подробнее см. СП)

Прежде всего необходимо создать файл отправки данных (собственно содержимое POST-запроса) и, при необходимости, подготовить двоичные данные.
Определяем разделитель разделов — границу boundary в POST-запросе в формате RFC (подробнее MIME: Организация данных ). В качестве границы может быть использована строка, состоящая из латинских букв и цифр.
Чтобы ничего не выдумывать, воспользуемся штатным классом 1С Предприятия УникальныйИдентификатор.

Code:
    //Подготовка переменных
    Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");

    //Определяем имя файла ответа от веб-сервера.
    ИмяФайлаОтвета = КаталогВременныхФайлов() + "answer.tmp";

Содержимое файла ответа будет представлять собой какой-либо контент, отданный скриптом на стороне веб-сервера агенту пользователя. Подробнее смотрите пример скрипта php и скриншот ниже.

Подготавливаем двоичные данные. В моём случае это файл архива zip, но может быть что угодно, хоть изображение.

Code:
    //Какой-то ранее созданный файл с двоичными данными.
    ИмяФайлаДляЗагрузки = "data.zip";


Передача содержимого файла
В 1С Предприятии отсутствуют средства чтения двоичных файлов в обычную строку, как в PHP или PERL.
Одним из способов получения строкового содержимого двоичного файла является кодирование с помощью штатных функций Base64Строка() или XMLСтрока(), при этом размер передаваемых данных увеличивается примерно на 30%. Декодировать содержимое файла на сервере можно при помощи функции php base64_decode() или аналогичных для используемого вами серверного ПО.
Другой способ состоит в использовании штатной функции ОбъединитьФайлы(<МассивФайлов>, <Имя результирующего файла>) (подробнее см. в СП). В этом случае формирование файла POST-запроса будет происходить немного сложнее.
Оба способа описаны ниже.

Впрочем, двоичные данные лучше закодировать, иначе при приёме на веб-сервере файл может быть повреждён или не принят вовсе, если он будет содержать URL-значащие символы. Особенно это касается XML-подобных или иных текстовых файлов.

Следует также помнить об ограничениях хостинга и контролировать размер передаваемых данных. Как правило, для php это 2Мб. (см. файл /usr/local/php5/php.ini)
; Maximum allowed size for uploaded files.
upload_max_filesize = 2M

В противном случе, на веб-сервере вы получите пустой POST-запрос.


    //Если файл кодируется
//Закодируем содержимое файла по Base64, то есть преобразуем его к URL-неактивному виду. //Base64 - специальный формат хранения данных в текстовом формате
СодержимоеФайла = Base64Строка(Новый ДвоичныеДанные(ИмяФайлаДляЗагрузки)); //Проверка размера кодированного файла. Если СтрДлина(СодержимоеФайла) > ДопустимыйРазмерФайлаВБайтах Тогда //Какие-то ваши действия, возможно Возврат; КонецЕсли; //Если файл не кодируется //Проверка размера обычного файла. Файл = Новый Файл(ИмяФайлаДляЗагрузки); Если Файл.Размер() > ДопустимыйРазмерФайлаВБайтах Тогда //Какие-то ваши действия, возможно Возврат; КонецЕсли; ИмяФайлаОтправки = КаталогВременныхФайлов() + "post.txt";


Создаём файл отправки или содержимое POST-запроса.

1. Вариант с передачей кодированного файла.

    КодироватьФайл = Истина;
    ФайлОтправки = Новый ЗаписьТекста(ИмяФайлаОтправки, КодировкаТекста.ANSI, Символы.ПС, Ложь);
    //Определяем раздел двоичных данных
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);
    //Указываем имя файла для передачи
    //На сервере оно появится в массиве $_FILES['datafile']['name']
    ФайлОтправки.ЗаписатьСтроку("Content-Disposition: form-data; name=""datafile""; filename=""" + ИмяФайлаДанных + """");
    //Указываем тип передаваемых данных.
    //С таким же успехом в Content-Type можно указать application/x-octet-stream
    ФайлОтправки.ЗаписатьСтроку("Content-Type: application/x-zip-compressed" + Символы.ПС + Символы.ПС);
    //Записываем кодированные двоичные данные
    ФайлОтправки.ЗаписатьСтроку(СодержимоеФайла);
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);

    //Определяем раздел для каких либо других POST-данных, например содержимого полей виртуальной HTML-формы.

    //Соответствует полю HTML-формы input type="submit" name="submit" value="Submit" /
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);
    ФайлОтправки.ЗаписатьСтроку("Content-disposition: form-data; name=""submit""" + Символы.ПС);
    ФайлОтправки.ЗаписатьСтроку("1");
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);

    //Соответствует полю HTML-формы input type="checkbox" name="decode" value="decode" /
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);
    ФайлОтправки.ЗаписатьСтроку("Content-disposition: form-data; name=""decode""" + Символы.ПС);
    ФайлОтправки.ЗаписатьСтроку(?(КодироватьФайл, "1", "0"));
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);

    //Соответствует полю HTML-формы input type="text" name="some_field" value="Some text" /
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary);
    ФайлОтправки.ЗаписатьСтроку("Content-disposition: form-data; name=""message""" + Символы.ПС);
    ФайлОтправки.ЗаписатьСтроку("Передача файла из базы данных 1С Предприятия");

    //Завершение сообщения для сервера
    ФайлОтправки.ЗаписатьСтроку("--" + Boundary + "--");

    ФайлОтправки.Закрыть();


2. Вариант с передачей обычного файла.

    КодироватьФайл = Ложь;
    //Определяем массив для процедуры ОбъединитьФайлы
    МассивФайловДляОбъединения = Новый Массив;

    //Формируем начальный фрагмент файла POST-запроса
    ИмяФайлаОтправкиНачало = ПолучитьИмяВременногоФайла("txt");
    ФайлОтправкиНачало = Новый ЗаписьТекста(ИмяФайлаОтправкиНачало, КодировкаТекста.ANSI, Символы.ПС, Ложь);
    //Определяем раздел двоичных данных
    ФайлОтправкиНачало.ЗаписатьСтроку("--" + Boundary);
    //Указываем имя файла для передачи
    //На сервере оно появится в массиве $_FILES['datafile']['name']
    ФайлОтправкиНачало.ЗаписатьСтроку("Content-Disposition: form-data; name=""datafile""; filename=""" + ИмяФайлаДляЗагрузки + """");
    //Указываем тип передаваемых данных.
    //С таким же успехом в Content-Type можно указать application/x-octet-stream или application/x-zip-compressed
    ФайлОтправкиНачало.ЗаписатьСтроку("Content-Type: application/x-octet-stream");
    ФайлОтправкиНачало.ЗаписатьСтроку("");
    ФайлОтправкиНачало.Закрыть();

    МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиНачало);

    //Копируем файл для загрузки во временный и добавляем в массив файлов для объединения
    ИмяФайлаДляЗагрузкиВременный = ПолучитьИмяВременногоФайла("tmp");
    КопироватьФайл(ИмяФайлаДляЗагрузки, ИмяФайлаДляЗагрузкиВременный);
    МассивФайловДляОбъединения.Добавить(ИмяФайлаДляЗагрузкиВременный);

    //Формируем конечный фрагмент файла POST-запроса
    ИмяФайлаОтправкиКонец = ПолучитьИмяВременногоФайла("txt");
    ФайлОтправкиКонец = Новый ЗаписьТекста(ИмяФайлаОтправкиКонец, КодировкаТекста.ANSI, Символы.ПС, Ложь);

    //Завершение раздела двоичных данных
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);

    //Определяем раздел для каких либо других POST-данных, например содержимого полей виртуальной HTML-формы.

    //Соответствует полю HTML-формы input type="submit" name="submit" value="Submit" /
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);
    ФайлОтправкиКонец.ЗаписатьСтроку("Content-disposition: form-data; name=""submit""" + Символы.ПС);
    ФайлОтправкиКонец.ЗаписатьСтроку("1");
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);

    //Соответствует полю HTML-формы input type="checkbox" name="decode" value="decode" /
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);
    ФайлОтправкиКонец.ЗаписатьСтроку("Content-disposition: form-data; name=""decode""" + Символы.ПС);
    ФайлОтправкиКонец.ЗаписатьСтроку(?(КодироватьФайл, "1", "0"));
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);

    //Соответствует полю HTML-формы input type="text" name="some_field" value="Some text" /
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary);
    ФайлОтправкиКонец.ЗаписатьСтроку("Content-disposition: form-data; name=""message""" + Символы.ПС);
    ФайлОтправкиКонец.ЗаписатьСтроку("Передача файла из базы данных 1С Предприятия");
    //Завершение сообщения для сервера
    ФайлОтправкиКонец.ЗаписатьСтроку("--" + Boundary + "--");
    ФайлОтправкиКонец.Закрыть();

    МассивФайловДляОбъединения.Добавить(ИмяФайлаОтправкиКонец);

    //Теперь сформированные фрагменты сообщения для сервера объединяем в один файл POST-запроса
    ОбъединитьФайлы(МассивФайловДляОбъединения, ИмяФайлаОтправки);


Формируем заголовок POST-запроса.

    ЗаголовокHTTP = Новый Соответствие();
    //Обязательные поля заголовка

    //Укажем формат данных Content-Type
    ЗаголовокHTTP.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);

    //Укажем длину POST-запроса Content-Length
    ФайлОтправки = Новый Файл(ИмяФайлаОтправки);
    РазмерФайлаОтправки = XMLСтрока(ФайлОтправки.Размер());
    ЗаголовокHTTP.Вставить("Content-Length", РазмерФайлаОтправки);

    //При необходимости зададим Referer, например таким образом
    СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
    СерверИсточник = НСтр(СтрокаСоединения, "Srvr") + НСтр(СтрокаСоединения, "Ref");
    ЗаголовокHTTP.Вставить("Referer", СерверИсточник);

Если вы получите ошибку сервера вида Failed sending data to the peer, попробуйте убрать параметр Referer из заголовка.

Инициализируем HTTPСоединение. При необходимости задаём параметры прокси.

    СерверПриемник = "www.some_site.ru"; //Без протокола . Естественно, следует указать свой адрес.
    Порт = "80"; //Это общепринятый порт. Возможно, для вашего сервера применяется другой. Конкретное значение уточните у хостера.

    //ИспользоватьПрокси - какая-то логическая переменная, может быть значение флажка на форме или переключатель
    Если ИспользоватьПрокси Тогда
        Прокси = Новый ИнтернетПрокси;
        Прокси.НеИспользоватьПроксиДляЛокальныхАдресов = Истина;
        Прокси.Пароль = "ПарольПрокси"; // укажите своё значение
        Прокси.Пользователь = "ПользовательПрокси"; // укажите своё значение
        НТТР = Новый HTTPСоединение(СерверПриемник, Порт, , , Прокси);
    Иначе
        НТТР = Новый HTTPСоединение(СерверПриемник, Порт);
    КонецЕсли;


Отправка данных серверу.

Здесь приведён код, общий для платформ 8.1, 8.2, 8.3.


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

    //Удаляем файлы POST-запроса и фрагменты сообщения. Больше они не нужны
    УдалитьФайлы(ИмяФайлаОтправки);
    Если НЕ КодироватьФайл Тогда
        Для каждого ЭлементМассива Из МассивФайловДляОбъединения Цикл
            УдалитьФайлы(ЭлементМассива);
        КонецЦикла;
    КонецЕсли;


Отправили данные, анализируем ответ сервера.

    ФайлОтвета = Новый Файл(ИмяФайлаОтвета);
    Если ФайлОтвета.Существует() Тогда
        ТекстОтвета = Новый ТекстовыйДокумент();
        ТекстОтвета.Прочитать(ИмяФайлаОтвета);
        Если ТекстОтвета.КоличествоСтрок() > 0 Тогда
            ОтветСервера = ТекстОтвета.ПолучитьТекст();
            #Если Клиент Тогда
                Сообщить(ОтветСервера);
            #КонецЕсли
        Иначе
            #Если Клиент Тогда
                Сообщить("Отправка файла на сервер: Получен пустой ответ сервера.");
            #Иначе
                ЗаписьЖурналаРегистрации("HTTPСоединение", УровеньЖурналаРегистрации.Ошибка, , , "Получен пустой ответ сервера.");
            #КонецЕсли
        КонецЕсли;

        //Удалим файл ответа. Больше он нам не нужен.
        УдалитьФайлы(ИмяФайлаОтвета);
    Иначе
        #Если Клиент Тогда
            Сообщить("Отправка файла на сервер: Ответ сервера не получен.");
        #Иначе
            ЗаписьЖурналаРегистрации("HTTPСоединение", УровеньЖурналаРегистрации.Ошибка, , , "Ответ сервера не получен.");
        #КонецЕсли
КонецЕсли;


Отправка файла на сервер в стиле платформы 8.3., 8.2.18 и позднее

Попытка
    АдресСкрипта = "some_script.php"; //Без протокола  и имени домена. Естественно, следует указать имя своего скрипта.

    //Формируем HTTP запрос
    ЗапросHTTP = Новый HTTPЗапрос(АдресСкрипта, ЗаголовокHTTP);
    ЗапросHTTP.УстановитьИмяФайлаТела(ИмяФайлаОтправки);  //Устанавливает имя файла, из которого будет прочитано тело POST-запроса.

    //Ответ от сервера получим в возвращаемом значении типа HTTPОтвет
    ОтветHTTP = НТТР.ОтправитьДляОбработки(ЗапросHTTP);
Исключение
    //Реализацию процедуры УстановитьHTML смотреть в прилагаемой обработке
    УстановитьHTML("Неудачная попытка соединения с " + СерверПриемник + ": " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

//Разрушаем объект HTTP-запроса для освобождения файла POST-запроса.
//В противном случае при попытке удаления файла получим ошибку совместного доступа.
ЗапросHTTP = Неопределено;

//Удаляем файлы POST-запроса и фрагменты сообщения. Больше они не нужны.
УдалитьФайлы(ИмяФайлаОтправки);
Для каждого ЭлементМассива Из МассивФайловДляОбъединения Цикл
    УдалитьФайлы(ЭлементМассива);
КонецЦикла;


Некоторые сервера после получения и обработки POST или GET-запроса могут вернуть не результат исполнения скрипта, а переадресовать на другую страницу, то есть вернуть код 301 Moved Permanently или 302 Moved Temporarily. В этом случае следует проверить код состояния ответа. Реализацию функции ПолучитьСодержимоеВебАдреса() смотрите на странице Получение содержимого указанного адреса url (вебстраницы) для 1С: Предприятия 8.2.18 - 8.3

//Анализируем и выводим ответ сервера в виде строки
//Для начала следует на всякий случай проверить код состояния ответа сервера
Если ОтветHTTP.КодСостояния = 301 или ОтветHTTP.КодСостояния = 302 Тогда //
    //Если сервер вернул один из статусов переадресации
    //301 Moved Permanently («перемещено навсегда») или 302 Moved Temporarily («перемещено временно»)
    //В этом случае можно попытаться получить содержимое страницы, на которую переадресовал сервер
    ЗаголовкиОтвета = ОтветHTTP.Заголовки;
    Если ЗаголовкиОтвета.Количество() > 0 Тогда
        //Адрес страницы содержится в поле Location заголовка ответа
        АдресСтраницы = ЗаголовкиОтвета.Получить("Location");
        Если Найти(АдресСтраницы, СерверПриемник + "/") = 0  Тогда
            АдресСтраницы = "http://" + СерверПриемник + "/" + АдресСтраницы;
        КонецЕсли;
        Если ЗначениеЗаполнено(АдресСтраницы) Тогда
            СтрокаОтветаСервера = ПолучитьСодержимоеВебАдреса(АдресСтраницы, , ЗаголовкиОтвета);
        КонецЕсли;
    КонецЕсли;
КонецЕсли;


Анализируем и выводим ответ сервера в виде строки.
СтрокаОтветаСервера = ОтветHTTP.ПолучитьТелоКакСтроку();
Если ЗначениеЗаполнено(СтрокаОтветаСервера) Тогда
    СтрокаОтветаСервера = СтрЗаменить(СтрокаОтветаСервера, Символы.ПС, "
"
); УстановитьHTML("Ответ сервера: " + СтрокаОтветаСервера); Иначе УстановитьHTML("Отправка файла на сервер: Получен пустой ответ сервера."); КонецЕсли; УстановитьHTML("Код состояния: " + XMLСтрока(ОтветHTTP.КодСостояния ), Истина);


Получаем и выводим HTTP-заголовки ответа сервера в виде соответствия: "Название заголовка" - "Значение".
ЗаголовкиОтвета = ОтветHTTP.Заголовки;
Если ЗаголовкиОтвета.Количество() > 0 Тогда
    УстановитьHTML("Заголовки ответа:", Истина);
    Для каждого КлючИЗначение Из ЗаголовкиОтвета Цикл
        УстановитьHTML(КлючИЗначение.Ключ + ": " + КлючИЗначение.Значение, Истина);
    КонецЦикла; //Для каждого КлючИЗначение Из ЗаголовкиОтвета
КонецЕсли;


Подробную реализацию отправки файла с кодированием и без кодирования смотрите в приложенных обработках Загрузка файлов на веб-сервер.epf или Отправка данных и загрузка файлов на веб-сервер 8.3.epf.

Отправка простого POST-запроса на сервер в стиле платформы 8.3., 8.2.18 и позднее, без использования промежуточных файлов

Code:
//Тело POST-запроса
ТелоPOSTЗапроса = "";
ТелоPOSTЗапроса = ТелоPOSTЗапроса + "&param1=" + Параметр1;
ТелоPOSTЗапроса = ТелоPOSTЗапроса + "&param2=" + Параметр2;
ТелоPOSTЗапроса = ТелоPOSTЗапроса + "&param3=" + Параметр3;
ТелоPOSTЗапроса = ТелоPOSTЗапроса + "&param4=" + Параметр4;

//POST-запрос на сервер-приёмник
СерверПриемник = "www.server_name.com"; //имя сервера без протокола (http) и порта
АдресСтраницыНаСервере = "/search.cgi"; //

ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP.Вставить("Content-Type", "application/x-www-form-urlencoded");

Таймаут = 120;
SSL =  ?(ЗащищенноеСоединение, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено);
НТТР = Новый HTTPСоединение(СерверПриемник, , , , , Таймаут, SSL);

Попытка
    //Формируем HTTP запрос
    ЗапросHTTP = Новый HTTPЗапрос(АдресСтраницыНаСервере, ЗаголовкиHTTP);
    ЗапросHTTP.УстановитьТелоИзСтроки(ТелоPOSTЗапроса); //Устанавливает строку, из которого будет прочитано тело POST-запроса.

    //Ответ от сервера получим в возвращаемом значении типа HTTPОтвет
    ОтветHTTP = НТТР.ОтправитьДляОбработки(ЗапросHTTP);
Исключение
    ТекстСообщения = НСтр("ru = 'Неудачная попытка соединения с '")  + СерверПриемник + ": " + ОписаниеОшибки();
    ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
    Возврат;
КонецПопытки;

ЗаголовкиHTTP = Новый Соответствие;
СтрокаОтветаСервера = "";
//Анализируем и выводим ответ сервера в виде строки
//Для начала следует на всякий случай проверить код состояния ответа сервера
Если ОтветHTTP.КодСостояния = 301 или ОтветHTTP.КодСостояния = 302 Тогда //
    //Если сервер вернул один из статусов переадресации
    //301 Moved Permanently («перемещено навсегда») или 302 Moved Temporarily («перемещено временно»)
    //В этом случае можно попытаться получить содержимое страницы, на которую переадресовал сервер
    ЗаголовкиОтвета = ОтветHTTP.Заголовки;
    Если ЗаголовкиОтвета.Количество() > 0 Тогда
        //Адрес страницы содержится в поле Location заголовка ответа
        АдресСтраницы = ЗаголовкиОтвета["Location"];
        Если Найти(АдресСтраницы, СерверПриемник + "/") = 0  Тогда
            АдресСтраницы = "http://" + СерверПриемник + "/" + АдресСтраницы;
        КонецЕсли;
        Если ЗначениеЗаполнено(АдресСтраницы) Тогда
            //Если сервер вернул cookies (http://ru.wikipedia.org/wiki/HTTP_cookie, http://www.faqs.org/rfcs/rfc6265.html?#41;,
            //вставим их в заголовки для передачи на страницу перехода
            Куки = ОтветHTTP.Заголовки["Set-Cookie"];
            Если ЗначениеЗаполнено(Куки) Тогда
                ЗаголовкиHTTP.Вставить("Cookie", Куки);
            КонецЕсли;
            СтрокаОтветаСервера = ПолучитьСодержимоеВебАдреса(АдресСтраницы, , , ЗаголовкиHTTP);
        КонецЕсли;
    КонецЕсли;
Иначе
    //Анализируем и выводим ответ сервера в виде строки
    СтрокаОтветаСервера = ОтветHTTP.ПолучитьТелоКакСтроку();
КонецЕсли;


Примерное содержимое скрипта-приёмника данных на веб-сервере "some_script.php". Скрипт вы также можете извлечь из макета обработки Загрузка файлов на веб-сервер.epf или Отправка данных и загрузка файлов на веб-сервер 8.3.epf.

Code:
<?
//Coded by Sergey aka Porutchik http://forum.aeroion.ru
//http://forum.aeroion.ru/topic446.html

//Читаем текстовые данные POST-запроса
$submit = ( isset($_POST['submit']) ) ? intval($_POST['submit']) : false;
$decode = ( isset($_POST['decode']) ) ? intval($_POST['decode']) : false;
$message = ( isset($_POST['message']) ) ? htmlspecialchars($_POST['message']) : '';

//Проверим user-agent, хотя большого толку от такой проверки нет. См. статью.
if ( $_SERVER['HTTP_USER_AGENT'] != '1C+Enterprise/8.1' )
{
    @header('HTTP/1.0 403 Forbidden');
    die('Hacking attempt');
}

if ( $submit )
{
    //Здесь работаем с содержимым переданного файла.
    $uploadFile = $_FILES['datafile'];
    $tmp_name = $uploadFile['tmp_name'];
    $data_filename = $uploadFile['name'];
    if ( !is_uploaded_file($tmp_name) ) 
    {
        die('Ошибка при загрузке файла ' . $data_filename);
    } 
    else 
    {
        //Считываем файл в строку
        $data = file_get_contents($tmp_name);

        if ($decode)
        {
            //При необходимости декодируем данные
            $data = base64_decode($data);
        }
        //Теперь нормальный файл можно сохранить на диске
        if ( !empty($data) && ($fp = @fopen($data_filename, 'wb')) )
        {
            @fwrite($fp, $data);
            @fclose($fp);
        }
        else
        {
            die('Ошибка при записи файла ' . $data_filename);
        }
        @header('HTTP/1.1 200 Ok');
        @header('Content-type: text/html; charset=windows-1251');
        $answer = "\n" . 'Файл <b>' . $data_filename . '</b> успешно загружен. ' . "\n" . 'Переданное сообщение: ' . $message;
        print ($answer);
    }
}
?>


В завершение статьи процитирую.
Обращаю ваше внимание, что указанная здесь методика освещает возможность загрузки файлов на сервер. Использование их "в чистом виде" без доработки может быть небезопасным, и является потенциальной возможностью для взлома вашего сайта. А именно, отсутствие обработки имени файла, который пришел на сервер, отсутствие авторизации, определения источника, посылающего файл, может дать злоумышленнику возможность загрузить и выполнить вредоносный код на вашем сайте. Рассмотрение способов защиты не входит в данную статью и остается на ваше усмотрение.


Список использованной литературы:

Protected Text:
Show


Download Отправка данных и загрузка файлов на веб-сервер 8.3.epf (33.21 KB). Added/Updated Fri 06 Nov, 2015 14:09. Downloaded 404 Time(s).
This file for registered users. Обработка, иллюстрирующая отправку данных, загрузку файлов на веб-сервер, скачивание файла с сервера для платформы 8.3.X, 8.2.18, 8.2.19.

Download Загрузка файлов на веб-сервер.epf (15.68 KB). Added/Updated Sat 02 Mar, 2013 16:23. Downloaded 405 Time(s).
This file for registered users. Устаревший вариант. Обработка, иллюстрирующая загрузку файлов на веб-сервер для платформы 8.1. и 8.2 до релиза 8.2.18. Для использования в 1С Предприятии 8.2. открыть в конфигураторе, согласиться на конвертацию.

Download ПросмотрИнфостарт.epf (11.76 KB). Added/Updated Mon 18 May, 2009 18:10. Downloaded 912 Time(s).
This file for registered users. Устаревший вариант. Пример POST-запроса без файлов для платформы 8.1. и 8.2 до релиза 8.2.18. Просмотр и авторизация на сайте infostart.ru. Для использования в 1С Предприятии 8.2. открыть в конфигураторе, согласиться на конвертацию.

#
1. downloadfile.png (73.51 KB). Viewed 1764 Time(s).    

downloadfile.png
2. uploadfile.png (46.85 KB). Viewed 5824 Time(s).    

uploadfile.png

_________________
Профессионал - это тот же дилетант, только знающий где ошибется. Генератор db_update.php для phpBB2 с некоторыми удобствами.
Как ставить моды. Что такое [SQL] и с чем его едят | Как правильно задавать вопросы и получать адекватные ответы | Правила форума
Бесплатная техподдержка только на форуме! Не надо стучаться в аську, скайп, слать емайлы, пытаться писать в приват. Спасибо за понимание. Please do not PM, ICQ, Skype or email me for support help - you won't get any reply. If you have a question or issue, post it in the appropriate forum/topic. Thanks!
Back to topOffline View user's profile Visit poster's website Skype Name
andreyershov

Заинтересовался


Joined: 19 Feb 2014
Show/Hide

Добрый день!
Подскажите, пожалуйста, как правильно передавать логин и пароль в POST запрос?
Задача стоит такая:
Для передачи данных для доставки необходимо направить POST запрос на адрес:
maxipost.ru/ap.....secure=...
+ POST параметр «data», содержащий XML

Сам параметр "data" нужно передавать как строку из xml документа.
Проверял контакт через Google PostMan, там параметры вставляются прям в строку запроса, а параметр data как ключ для form-data

VH770gvMTa4.jpg

Code:
Процедура Загрузить()
    
    Логин = "24f54226a74ec88520d56f609e31c6a7";
    Пароль = "24f54226a74ec88520d56f609e31c6a7";
    Шифр = Формат(ТекущаяДата(),"ДФ=yyyy.MM.dd")+"T00:00:00&"+Пароль;
    ШифрПароль = MD5Eng(Шифр);
    
    ТекстДанных = Новый ТекстовыйДокумент;
    ТекстДанных.Прочитать(ИмяФайлаДляЗагрузки);
    Текст = ТекстДанных.ПолучитьТекст();
    
    
    Сервер = "http://www.maxipost.ru";
    Ресурс = "http://www.maxipost.ru/api/set_zakaz_to_db_test.php?account="+Логин+"&secure="+Пароль;
    HTTP =  Новый HTTPСоединение(Сервер);
    ФайлЗапроса = ПолучитьИмяВременногоФайла();
    ТекстовыйФайл = Новый ТекстовыйДокумент;
    ТекстовыйФайл.УстановитьТекст("&data=" + СокрЛП("Текст"));
    ТекстовыйФайл.Записать(ФайлЗапроса, КодировкаТекста.UTF8);
    ФайлРезультата = ПолучитьИмяВременногоФайла();
    ЗаголовокHTTP = Новый Соответствие();
    ЗаголовокHTTP.Вставить("Content-Type", "application/x-www-form-urlencoded");
    ЗаголовокHTTP.Вставить("Accept-Language", "ru");
    ЗаголовокHTTP.Вставить("Accept-Charset", "utf-8");
    ЗаголовокHTTP.Вставить("Content-Language", "ru");
    ЗаголовокHTTP.Вставить("Content-Charset", "utf-8");
    HTTP.ОтправитьДляОбработки(ФайлЗапроса, Ресурс, ФайлРезультата, ЗаголовокHTTP);
    Ответ = Новый ТекстовыйДокумент();
    Ответ.Прочитать(ФайлРезультата, КодировкаТекста.UTF8);
    ТекстОтвета = Ответ.ПолучитьТекст();
    УдалитьФайлы(ФайлЗапроса);
    УдалитьФайлы(ФайлРезультата);
КонецПроцедуры    


Такой код выдает ошибку работы с интернетом.

Back to topOffline View user's profile
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

Посмотрите в синтаксис-помощнике класс HTTPЗапрос, УстановитьТелоИзСтроки(). Во-вторых, примеры обработок смотрите внимательней.
Code:
    Сервер = "www.maxipost.ru"; //указывается без http://
    Ресурс = "api/set_zakaz_to_db_test.php"; //указывается без http:// и имени домена 
Back to topOffline View user's profile Visit poster's website Skype Name
andreyershov

Заинтересовался


Joined: 19 Feb 2014
Show/Hide

А логин и пароль надо в строку ресурса вписывать или размещать в теле запроса?
Code:
Ресурс = "/api/set_zakaz_to_db_test.php?account="+Логин+"&secure="+Пароль; 

Так должно соединяться?
Back to topOffline View user's profile
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

Не обязательно все параметры для передачи методом POST должны отправляться в теле запроса. Если методом GET, то надо указывать в параметрах адреса страницы.

Code:
//Получаем данные с HTTP-сервера, используя GET-запрос.

ЗапросСерверу = Новый HTTPЗапрос("some_script.php?param1=ppppp&amp;param2=xxxx");
Соединение = Новый HTTPСоединение("www.some_site.ru",,,,, Истина);
HTTPОтветСервера = Соединение.Получить(ЗапросСерверу);
ТекстОтветСервера = HTTPОтветСервера.ПолучитьТелоКакСтроку(); 


У вас написано, в общем-то верно, только можно обойтись без временного файла POST-запроса и ответа, если используется релиз 1С Предприятия 8.2.18 и позднее.

Добавлено спустя 1 час 36 минут 31 секунду:

Можно отправлять и так. В обработке это продемонстрировано.
Back to topOffline View user's profile Visit poster's website Skype Name
andreyershov

Заинтересовался


Joined: 19 Feb 2014
Show/Hide

Подскажите по методу GET, пожалуйста.
Пытаюсь получить ответ от сервера транспортной компании
Code:
    ИмяФайлаОтвета = "D:\GETotvet.xml";
    Соединение = Новый HTTPСоединение("www.maxipost.ru",,,,, Истина);
    Соединение.Получить(АдресСтраницы, ИмяФайлаОтвета);
 

На методе .Получить() выдает ошибку "Ошибка работы с Интернет: Peer certificate cannot be authenticated with known CA certificates"
Я так понимаю, что ошибка в неком сертификате. Как с этим можно бороться? Надо запрашивать сертификат в транспортной компании?
Back to topOffline View user's profile
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

Post Mon 24 Feb, 2014 16:02 Download Post Reputation: 88
 Защищённое соединение по протоколу https с использованием сертификатов для платформы 8.3
У них, скорее всего, поддержка защищённого соединения по протоколу HTTPS. Попробуйте как в примере (подробнее смотреть в СП)
Code:
    ssl = Новый ЗащищенноеСоединениеOpenSSL(
        Новый СертификатКлиентаWindows(СпособВыбораСертификатаWindows.Авто), Новый СертификатыУдостоверяющихЦентровWindows()
    );
    Соединение = Новый HTTPСоединение(
        "www.maxipost.ru", // хост запрашиваемого сервера
        443, // порт по умолчанию для используемого протокола https
        ,,,
        5, // таймаут в секундах
        ssl // защищенное HTTPS соединение
    );
    ИмяФайлаОтвета = "D:\GETotvet.xml";
    Соединение.Получить(АдресСтраницы, ИмяФайлаОтвета); 

Если не помогло, читаем темы
Peer certificate cannot be authenticated with known CA certificates
Включение своего сертификата в список доверенных для 1С в файл cacert.pem
Если не помогло, обратиться к админам МаксиПост за разъяснениями, что используется: OpenSSL или NSS.

_________________
Профессионал - это тот же дилетант, только знающий где ошибется. Генератор db_update.php для phpBB2 с некоторыми удобствами.
Как ставить моды. Что такое [SQL] и с чем его едят | Как правильно задавать вопросы и получать адекватные ответы | Правила форума
Бесплатная техподдержка только на форуме! Не надо стучаться в аську, скайп, слать емайлы, пытаться писать в приват. Спасибо за понимание. Please do not PM, ICQ, Skype or email me for support help - you won't get any reply. If you have a question or issue, post it in the appropriate forum/topic. Thanks!
Back to topOffline View user's profile Visit poster's website Skype Name
andreyershov

Заинтересовался


Joined: 19 Feb 2014
Show/Hide

Post Mon 24 Feb, 2014 16:16 Download Post Reputation: 0
 Защищённое соединение по протоколу https для платформы 8.2.18 и позднее
Спасибо большое! Заработало!!
Использовал упрощенную версию предложенного кода:
Code:
    ssl = Новый ЗащищенноеСоединениеOpenSSL;
    Соединение = Новый HTTPСоединение(
    "www.maxipost.ru",
    443, // порт по умолчанию для используемого протокола. 
    ,,,
    5, // таймаут в секундах
    ssl // защищенное HTTPS соединение
    );
    ИмяФайлаОтвета = "D:\GETotvet.xml";
    Соединение.Получить(АдресСтраницы, ИмяФайлаОтвета);
Back to topOffline View user's profile
LelPalna Gender:Female

Участница


Joined: 24 Mar 2014
Show/Hide

Добрый день!
Sergey, бьюсь и никак не могу добиться результата.. Надеюсь на Вашу помощь в следующем вопросе:
БухгалтерияПредприятия 2.0. С надстройкой, где реализовано подключение из 1С к веб-сервисам поставщиков. Веб-сервисы у всех разные, у всех свои сертификаты. :

Code:

    Попытка
        //Новый HTTPСоединение("https://sofi.aviroom.ru:30443/orawsv/SOFI_RAO/P_CRSDATA?wsdl")
        
        Если Лев(Определение, СтрДлина("https://")) = "https://" Тогда
            ПутьБезПротокола = Сред(Определение, СтрДлина("https://")+1);
            ПозСлеш = Найти(ПутьБезПротокола, "/");
            ДопСтрока = Сред(ПутьБезПротокола, ПозСлеш+1);
            АдресПорт = Лев(ПутьБезПротокола, ПозСлеш-1);
            ПозДвоеточие = Найти(АдресПорт, ":");
            Если ПозДвоеточие Тогда
                Адрес = Лев(АдресПорт, ПозДвоеточие-1);
                Порт = Сред(АдресПорт, ПозДвоеточие+1);
            Иначе
                Адрес = АдресПорт;
                Порт = "443";
            КонецЕсли;
            ИмяПользователя = "SOFI_SA";
            ПарольПользователя = "af39fsdR27";
            
            Соединение = Новый HTTPСоединение(Адрес, Число(Порт), ИмяПользователя, ПарольПользователя,, Истина);
            ВремФайл = ПолучитьИмяВременногоФайла("xml");
            Соединение.Получить(ДопСтрока, ВремФайл);
            Чтение = Новый ЧтениеТекста(ВремФайл);
            Строка = Чтение.Прочитать();
            Чтение.Закрыть();
            Строка = СтрЗаменить(Строка, "http://"+Адрес+":"+Порт, "https://"+Адрес+":"+Порт);
            Строка = СтрЗаменить(Строка, "http://"+Адрес+"/", "https://"+Адрес+"/");
            Запись = Новый ЗаписьТекста(ВремФайл);
            Запись.Записать(Строка);
            Запись.Закрыть();
            МоеОпределение = "file:///"+СтрЗаменить(ВремФайл, "\", "/");
            
            Если ПустаяСтрока(ИмяПользователя) Тогда
                WSОпределение = Новый WSОпределения(МоеОпределение);
            Иначе
                WSОпределение = Новый WSОпределения(МоеОпределение, ИмяПользователя, ПарольПользователя);
            КонецЕсли;
            
            УдалитьФайлы(ВремФайл);
        Иначе
            Если ПустаяСтрока(ИмяПользователя) Тогда
                WSОпределение = Новый WSОпределения(Определение);
            Иначе
                WSОпределение = Новый WSОпределения(Определение, ИмяПользователя, ПарольПользователя);
            КонецЕсли;
        КонецЕсли;
        
        URIПространстваИмен = WSОпределение.Сервисы[0].URIПространстваИмен;
        ИмяСервиса = WSОпределение.Сервисы[0].Имя;
        ПортСервиса = WSОпределение.Сервисы[0].ТочкиПодключения[0].Имя;
        Прокси = Новый WSПрокси(WSОпределение, URIПространстваИмен, ИмяСервиса, ПортСервиса);
        Прокси.Пользователь = ИмяПользователя;
        Прокси.Пароль= ПарольПользователя;
    Исключение
        ПодробноеОписание(ИнформацияОбОшибке());
    КонецПопытки;
    Возврат Прокси;


Все это счастье отлично работало до выхода платформы 8.2.19.80. Теперь при попытке получения HTTPСоединения у пары поставщиков при выполнении метода "Получить" вылетает с ошибкой:
Ошибка при вызове метода контекста (Получить)
[1]--> По причине: Ошибка работы с Интернет: SSL connect error

При этом при подключении к другим поставщикам, все работает как работало.Корневой сертификат установлен, ошибок при открытии ссылки в браузере нет.. В cacert.pem прописывала отдельно, хотя он итак там есть (реализовано в программе).
Можете подсказать что делать?
Back to topOffline View user's profile
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

Ваша тема? Не могу подключиться к веб-сервису, начиная с платформы 8.2.19.80
Попробуйте переписать Соединение = Новый HTTPСоединение по примеру из поста Защищённое соединение по протоколу https с использованием сертификатов для платформы 8.3 или поста ниже.
Поднять платформу до последней в линии 8.2 или 8.3.

_________________
Профессионал - это тот же дилетант, только знающий где ошибется. Генератор db_update.php для phpBB2 с некоторыми удобствами.
Как ставить моды. Что такое [SQL] и с чем его едят | Как правильно задавать вопросы и получать адекватные ответы | Правила форума
Бесплатная техподдержка только на форуме! Не надо стучаться в аську, скайп, слать емайлы, пытаться писать в приват. Спасибо за понимание. Please do not PM, ICQ, Skype or email me for support help - you won't get any reply. If you have a question or issue, post it in the appropriate forum/topic. Thanks!
Back to topOffline View user's profile Visit poster's website Skype Name
LelPalna Gender:Female

Участница


Joined: 24 Mar 2014
Show/Hide

Моя.. Как видите, миллион ответов)
Переписывала в виде:
Code:
// адрес: https://sofi.aviroom.ru:8443/orawsv/SOFI_RAO/P_CRSDATA?wsdl
        ssl = Новый ЗащищенноеСоединениеOpenSSL;
        Попытка
            Соединение = Новый HTTPСоединение("sofi.aviroom.ru", "8443", ИмяПользователя, ПарольПользователя,,, ssl);
            ИмяФайлаОтвета = ПолучитьИмяВременногоФайла("xml");
            Соединение.Получить("orawsv/SOFI_RAO/P_CRSDATA?wsdl", ИмяФайлаОтвета); 
        Исключение
            ПодробноеОписание(ИнформацияОбОшибке());
        КонецПопытки;

Установила вчера платформу 8.2.19.90.
Все верно, но все равно выходит сообщение про Ошибка работы с Интернет: SSL connect error, хоть и СП уверяет, что ЗащищенноеСоединениеOpenSSL "предназначен для установки защищенного SSL-соединения без проверки сертификата сервера и без предоставления клиентского сертификата."
Насчет ОтправитьДляОбработки.. Запуталась с HTTPЗапросом
Back to topOffline View user's profile
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

В вашем случае ОтправитьДляОбработки не нужно.
Видимо, у той несчастной пары поставщиков сервера перестали дружить с 1С платформой позднее 8.2.19.80, или платформа позднее 8.2.19.80 перестала дружить с некоторыми защёнными серверами и их сертификатами.
Или мне самому нормально браться за это дело, или вам вернуть прежнюю платформу и ждать, когда 1С исправит ошибку. Больше ничем не помогу.

_________________
Профессионал - это тот же дилетант, только знающий где ошибется. Генератор db_update.php для phpBB2 с некоторыми удобствами.
Как ставить моды. Что такое [SQL] и с чем его едят | Как правильно задавать вопросы и получать адекватные ответы | Правила форума
Бесплатная техподдержка только на форуме! Не надо стучаться в аську, скайп, слать емайлы, пытаться писать в приват. Спасибо за понимание. Please do not PM, ICQ, Skype or email me for support help - you won't get any reply. If you have a question or issue, post it in the appropriate forum/topic. Thanks!
Back to topOffline View user's profile Visit poster's website Skype Name
LelPalna Gender:Female

Участница


Joined: 24 Mar 2014
Show/Hide

Ясно. спасибо!
временно, конечно, вернула платформу, но это лишь временная мера.
Подскажите только, пожалуйста, в моем случае чему "равен" АдресРесурса? (свойство HTTPЗапроса). С этими танцами с бубном уже во всем начинаю сомневаться
Back to topOffline View user's profile
Sergey Gender:Male


Местный босс - администратор


Joined: 06 Jan 2005
Show/Hide

АдресРесурса - Адрес страницы на сервере без протокола (http://, , etc), доменного имени сервера (хоста), порта. Выделенная часть адреса https ://sofi.aviroom.ru:8443/orawsv/SOFI_RAO/P_CRSDATA?wsdl и есть АдресРесурса
Back to topOffline View user's profile Visit poster's website Skype Name
LelPalna Gender:Female

Участница


Joined: 24 Mar 2014
Show/Hide

Всё так. Спасибо.
Back to topOffline View user's profile
Display posts from previous:   

Summary Rating For >> Передача / получение файлов и данных на веб-сервер средствами 1С:Предприятие 8.X методом POST / GET
Average Rating: 3.45 :: Min Rating: 0 :: Max Rating: 5 :: Number of Ratings: 11
Choose Rating: 1   2   3   4   5  


Similar Topics
Topic Author Forum Replies Last Post
No new posts Функция. Получение содержимого адреса url (вебстраницы) методом GET для 1С: Предприятия 8.2....
взаимодействие с веб-сервером
Универсальная функция, позволяющая получить содержимое ответа HTTP-сервера. Пример использования можно посмотреть в обработке 516 из статьи Передача файлов и данных на веб-сервер средствами 1С:Предприятие 8.X методом
Sergey 1Сv8: Программирование, отчёты, обработки, статьи 0 Sun 02 Mar, 2014 21:55 View latest post
Sergey
No new posts Передача параметров / значений во внешнюю печатную форму для конфигураций на БСП (1С:Предпри...
Обработка (управляемое приложение, внешняя печатная форма). Открытие диалога перед печатью
В некоторых случаях перед печатью документа требуется вручную указать какие-либо значения или параметры и передать в процедуру Печать() обработки. Для конфигураций линии УТ 10.3, БП 2.0 есть возможность передачи
Sergey 1Сv8: Программирование, отчёты, обработки, статьи 32 Sat 06 Jan, 2018 16:57 View latest post
ОТВидение_77
No new posts Шифрование файлов
Хотят хранить файлы с оргиналами документов на сервере, но в шифрованном виде и чтобы 1С-ка могла расшифровать. Есть ли какие-то стандартные способы шифрования?
Михута_Сергей 1Сv8: Программирование, отчёты, обработки, статьи 1 Tue 03 Mar, 2015 16:55 View latest post
Sergey
No new posts Функция. Чтение значений реквизитов объекта в структуру
1С: Предприятие 8.Х
Универсальная функция, позволяющая прочитать в структуру или простую переменную значения указанных или всех реквизитов произвольного объекта ссылочного типа, в том числе системных (дата, номер, код, наименование,
Sergey 1Сv8: Программирование, отчёты, обработки, статьи 0 Sun 25 Jul, 2010 12:17 View latest post
Sergey
No new posts [ Poll ] Общий журнал документов в управляемом приложении (1С: Предприятие 8.2)
обработка (управляемое приложение)
Добрый день, коллеги! Нашел Ваш форум - очень порадовал качественный контент :) В качестве прописки предлагаю обработку Общий журнал документов Вот, ссылка :) Обработка ранее выкладывалась на инфостарте. А ещё есть
Nike.Kolpinsky 1Сv8: Программирование, отчёты, обработки, статьи 1 Fri 17 May, 2013 22:15 View latest post
Sergey






All times are UTC + 3 hours
Users browsing this topic:
Registered Users: None

Jump to:   
printer-friendly view
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum
/a
Username:

Password:

Log me on automatically each visit
  Яндекс.Метрика
CrackerTracker © 2004 - 2018 CBACK.de