Работа с файлами (обычная и управляемая форма)




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

44 Comments

  1. Malfarion

    С клиента на сервер

    НачатьПомещениеФайла(..)

    С сервера на клиент

    ПолучитьФайл(…)

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

    Reply
  2. Xershi

    (1)

    НачатьПомещениеФайла

    В справке говорится, что нужно указать:

    В веб-клиенте, если расширение работы с файлами не установлено, то параметр <ПомещаемыеФайлы>:

    в интерактивном режиме должен иметь тип ДиалогВыбораФайла,

    в неинтерактивном режиме СсылкаНаФайл.

    Я использую не интерактивный режим. Что вы в ссылку на файл помещаете?

    А для

    ПолучитьФайл

    Выйдет что обязательно пользователю диалог кидать, что по моему мнению не всегда нужно!

    <Интерактивно> (необязательный)

    Тип: Булево.

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

    В веб-клиенте параметр должен быть равен Истина. В противном случае будет сгенерировано сообщение об ошибке.

    В новой версии платформы 8.3.15 разработчики сделали новые методы работы:

    https://wonderland.v8.1c.ru/blog/unifikatsiya-metodov-raboty-s-faylami/

    Но пока не понятно нужно ли платформа для них или режим совместимости.

    Кстати и далее там есть ссылка:

    https://wonderland.v8.1c.ru/blog/uluchshenie-raboty-s-faylami-v-veb-kliente/

    Которая позволяет не использовать расширение работы с файлами с версии платформы 8.3.13.1513, если указывать диалог, т.е. работать интерактивно, без привязки пути файла на клиенте к реквизиту.

    Reply
  3. Xershi

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

    Reply
  4. Malfarion

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

    Reply
  5. Xershi

    (4) не универсально. Интересовал конкретный пример.

    Reply
  6. androgin

    треш какой-то)))

    Reply
  7. Xershi

    (1) реализовал данные методы. Но как было сказано для корректной работы данных методов нужна платформа 8.3.13.1513 и выше. Режим совместимости конфигурации не влияет.

    И на мобильной платформе параметр <Интерактивно> игнорируется и диалоговое окно выбора файла не отображается никогда.

    Что делает реализацию еще более ограниченной.

    Поэтому выкладываю обработку отдельным файлом.

    Reply
  8. Vida

    С сервера на клиент по упрощенной версии 2:

    Диалог отлично показывается и отрабатывает на Тонком клиенте, а в веб-клиенте IE показывает странный диалог, на который не реагирует.

    Подозреваю что это где то в настройках IE. Подскажите где искать?

    Вот кусок моего кода:

    ПолноеИмяФайла = КаталогЭкспортаДокументов + МассивФайлов[Сч].Имя;
    ПолучитьФайл(МассивФайлов[Сч].Хранение, ПолноеИмяФайла, Истина);
    
    Reply
  9. Xershi

    (8) почитайте ограничение. Ничего странного!

    Когда выпустят стабильную версию 8.3.15 сделаю 3 версию, возможно они полный путь на клиенте получат иначе тоже самое будет.

    Reply
  10. Vida

    (9) да, ждем 8.3.15

    А пока посоветуйте как быть? Попробовать по 1 сложной версии?

    Reply
  11. Vida

    Прошу подсказки по первому варианту ЧЯДНТ

    ПолучаемыеФайлы = Новый Массив;
    Для Сч = 0 По МассивФайлов.Количество() — 1 Цикл
    
    ОписаниеПередаваемогоФайла = Новый ОписаниеПередаваемогоФайла(МассивФайлов[Сч].Имя, МассивФайлов[Сч].Хранение);
    ПолучаемыеФайлы.Добавить(ОписаниеПередаваемогоФайла);
    
    КонецЦикла;
    ОповещениеОЗавершении = Новый ОписаниеОповещения(«ВыполнитьПослеПолученияФайлов», ЭтотОбъект);
    НачатьПолучениеФайлов(ОповещениеОЗавершении, ПолучаемыеФайлы, КаталогЭкспортаДокументов, Ложь);
    

    Показать

    На тонком клиенте отрабатывает и файл создает,

    на веб-клиенте задает вопрос нужно ли сохранить файл

    (и кто его просил вопросы задавать) и никакого файла нет((

    хотя в ОповещениеОЗавершении вместо открытия у меня сообщение об успехе с полным именем — его выводит

    пити разные задавала не помогает

    складывается впечатление что в IE что-то не так, полазила там — ничего не нашла

    Reply
  12. Xershi

    (11) для начала вы не описали что у вас в переменных, а во вторых посмотрите какой код написан в примере или скачайте обработку.

    Разница же видна не вооруженным взглядом.

    Reply
  13. Xershi

    (10) первый и второй вариант практически не отличаются.

    Reply
  14. Vida

    (12) Обработку скачала.

    Да, код несколько упростила, но думала не критично — раз на тонком выполняется.

    Мои переменные

    1) МассивФайлов состоящий из структуры:

    Имя (просто название без пути)

    Хранение (адрес указывающий на значение во временном хранилище)

    2)КаталогЭкспортаДокументов путь куда должно сохраняться состоит из выбранного в диалоге и «/», если не хватает

    Прощу подсказать, что видно невооруженным глазом? У меня уже замылился наверное.

    Reply
  15. Xershi

    (14) скорее всего косяк в КаталогЭкспортаДокументов. Создайте лучше тему для обсуждения вашего написания кода.

    Reply
  16. Xershi

    (11) как оказалось у код был рабочий, просто были проблемы с ОС или антивирусом, и файл получался пустой!

    Reply
  17. ssn5810

    Можно указать конкретное место на сервере куда перемещаем файл с клиента ???

    Reply
  18. Xershi

    (17) да. Из описания и скриншотов это было не понятно?

    Reply
  19. ssn5810

    Зачем вопросы, проще сразу подсказать.

    В итоге мне нужно загрузить текстовый (txt) файл в табличную часть внешней обработки…..

    У меня пишет файл не найден…и текст переданного файла.

    Reply
  20. Xershi

    (19) разбирайтесь с настройками вашего сервера. И по данному описанию не понятно что вы делаете и как.

    Reply
  21. ssn5810

    понятно, спасибо за помощь…

    Reply
  22. Xershi

    Скачал 8.3.15.1489.

    Перевел конфигурацию в режим совместимости 8.3.15.

    Решил просто заменить на новые методы НачатьПомещениеФайловНаСервер.

    И получаю ошибку:

    Ошибка преобразования данных XDTO:
    НачалоСвойства: param Форма: Элемент Тип: {http://www.w3.org/2001/XMLSchema}anyType
    по причине:
    Ошибка отображения типов:
    Отсутствует отображение для типа ‘ОписаниеПомещенногоФайла’

    ОписаниеПередаваемогоФайла преобразуется в ОписаниеПомещенногоФайла, а оно не доступно на сервере.

    Проверил. Ошибка вылетает даже если оставить конфигурацию на 8.3.14.

    Reply
  23. androgin

    (22) БРЕД!! Я перевел все методы в нетиповой на новые методы и прекрасно отрабатывает, как с диалогом, так и без!

    Ничего там не подменяется)))

    Ничто не мешает вам создать общие функции ВыгрузитьФайлы/ЗагрузитьФайлы (например) и вызывать их с оповещениями и параметрами.

    Reply
  24. Xershi

    (23) почитайте внимательно что написано и посмотрите что конфигуратор выдает.

    В любом случае в 3 версии все корректно работает.

    Reply
  25. androgin

    (24) я не только читаю, но и практикую, к сведению!

    Reply
  26. Светлый ум

    (23) Бывают и экзотические косяки, просто вы везунчик или мало вариантов реализовывали

    Reply
  27. Светлый ум

    Закреплю описание статьи, теперь буду так оформлять +1

    Reply
  28. Xershi

    (26) Вы про что? Есть 3 вариант событий?

    Reply
  29. Светлый ум

    (28) я не про ваш функционал а про работу с файлами в целом

    Reply
  30. androgin

    (26) вы не читаете, что вам пишут?

    Синтаксис откройте! Там все варианты перечислены!

    Я не вижу реализации их у вас! Зато много слов в воздух

    Reply
  31. Xershi

    (29) понял. Да реализованы базовые сценарии обработки, что в 90% покроет потребность разработчика. Остальное конечно пилить, как нужно клиенту!

    Reply
  32. ccserg

    второй вариант не хочет работать

    вроде как без расширения должно работать

    Reply
  33. Xershi

    (32) не указана платформа, тип клиента и последовательность действий. Внимательно прочтите описание.

    Reply
  34. ccserg

    (33)

    windows_8_3_15_1534

    веб клиент

    открываю файл , жму Загрузить с клиента на сервер

    Reply
  35. Xershi

    (34) и вылетает ошибка?

    Reply
  36. ccserg

    (35) да

    Reply
  37. Xershi

    (36) завтра проверю на 8.3.15.

    Возможно надо использовать 3 версию.

    Reply
  38. Xershi

    (36) проверил, да все верно. Это операция требует расширения. Как сказано в описании работа без расширения возможна только в интерактивных операциях, т.к. доступа к файловой системе у 1С нету.

    Reply
  39. ccserg

    (38)

    так а как решить ? расширение установить ?

    расширение скачивается , устанавливается , но все равно не пашет

    это наверно уже другая проблема правда

    Reply
  40. Xershi

    (39) данная кнопка работает только с расширением. Да это другая проблема. Если не получается решить, поменяйте браузер.

    Reply
  41. Yashazz

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

    Reply
  42. Xershi

    (41) а чем содержание не угодило?

    Reply
  43. Yashazz

    (42) Да содержание тоже вполне себе очень даже, но не настолько восторг, чтоб прям плюсить. Просто хорошее изложение общеизвестных вещей.

    Кстати, вкину свои 5 копеек: теперь появился новый способ передавать файловые данные на сервер. Можно на клиенте получить двоичные данные, забросить их на сервер и там не сохранять во временные файлы, как раньше делали, а обрабатывать через буфер как файловый поток. Правда, пока у платформы на это есть ограничения (табдокумент, например, кушает только mxl и ods), но, думаю, допилят.

    Reply
  44. Xershi

    (43) вы не до конца ознакомились с публикацией? Я не использую временные файлы!

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

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

    В свое время пришлось на одном источнике руками набивать данный код, а здесь я сделал так что бери и копируй!

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *