Доброго времени суток. Встала задача - реализовать загрузку каталога из двух csv-файлов: файла с разделами каталога и файла с товарами с разброской свойств, характеристик товаров и привязкой к разделам. Создание товаров/разделов - не вижу смысла описывать, остановлюсь более детально на механизме обработки csv-файла.
Для начала, рекомендую ознакомиться с постом. Мой механизм чтения CSV - практически полностью идентичен (с небольшим дополнением).
Вот так получаем ассоциативный массив из csv-файла Построчно: * Подключаем CSV-класс * Читаем файл (при этом, первую строку также считываем) * Загружаем файл, который был добавлен в файловый input с именем "products_csv" * устанавливаем в качестве разделителя запятую * объявляем массив, в который будем помещать строки * объявляем массив, в который будем помещать заголовки полей * обрабатываем каждую строку файла * Если массив заголовков еще пустой, то заполняем его. * Иначе - перебираем все заголовки полей и формируем ассоциативный массив на основании данных строки файла * помещаем сформированный массив в общий контейнер.
Ну вот. Данные из файла считали. Дальше их необходимо обработать. Загрузить сразу все одним комом - не реально (Разделов у меня было 144 - они бы загрузились. А вот товаров - несколько тысяч. Тут бы сервер и объяснил мне на сколько я не прав...), следовательно, нужно обрабатывать блоками. Я выбрал вариант обработки каждой строки по отдельности. Для этого получился небольшой JS скрипт с отправкой данных через ajax-post-запросы:
<div id="loading"><p class="persents"><?=Loc::getMessage('PAI_LOADING');?><span class="pv">0</span>% (<?=Loc::getMessage('PAI_ROW');?><span class="rv">1</span>/<?=count($arRows)?>) </p></div>
<sc ript type="text/javascript">
var ajaxurl = '<ajax_url_path>'; // url to pass ajax requests
var Rows = <?=json_encode($arRows);?>;
var countRows = <?=count($arRows);?>;
function work_with_row(num, Row, d){
var Persents = (parseInt(num)+1)*100 / parseInt(countRows);
$('p.persents').find('span.pv').html(Math.round(Persents));
$('p.persents').find('span.rv').html(parseInt(num)+1);
$.ajax({
type: "POST",
url: ajaxurl,
data: {action: 'AddProduct', ProductData: Row},
dataType: "json",
success: function (data) {
d && d.resolve();
},
onfailure: function(){
d && d.resolve();
}
});
}
$(document).ready(function(){
var wait = BX.showWait('loading');
var deferreds = [];
var i=10;
$.each(Rows,function(index,value){
var d = new $.Deferred();
window.setTimeout(function() { work_with_row(index,value,d) }, 1000*index+(i++));
deferreds.push(d);
});
$.when.apply($, deferreds).done(function () {
$('p.persents').html('<?=Loc::getMessage('PAI_LOAD_DONE')?>');
BX.closeWait('loading',wait);
});
});
</sc ript>
Построчно: * div-контейнер, в котором будет публиковаться информация о состоянии загрузки * задаем переменную, в которой прописываем адрес, куда будем отправлять ajax-запросы * в переменную Rows помещаем считанные из csv-строки * в переменную countRows записываем количество строк для последующего подсчета текущего состояния загрузки * описываем функцию для обработки каждой записи * определяем текущий статус загрузки в процентном и абсоллютном соотношениях * далее отправляем аякс запрос, результаты которого помещаем в очередь на вывод пользователю * далее описываем функцию, котора отрабатывает сразу после загрузки страницы, т.е. после чтения csv-файла * показываем прелоадер в правом верхнем углу блока с ID=loading * определяем массив для очереди * устанавливаем приращение для очереди * перебираем все записи, при этом вызываем функцию обработки записи с интервалом * когда обработка завершена - выводим пользователю соответствующее сообщение и убираем прелоадер
Все! Вот такой вот вышел очередной опыт в переносе каталога из одной системы - в другую.
Алексей Попович смотрите, чем плох такой подход как у вас 1. вы вытаскиваете в паблик записи из файла, хотя могли бы обработать их еще на сервере (задежка по времени на лишнюю передачу данных) 2. снова отправляете эти же данные обратно на сервер из паблика (опять потери траффика) Итого:
вместо того, чтобы просто быстро и пошагово обрабатывать тяжелые CSV в пределах сервера - вы гоняете их между сервером и броузером туда и обратно.
Коваленко Алексей, благодарю за комментарий! В следующий раз обязательно попробую сделать загрузку без ajax. Тем более что данный пост был предназначен больше для примера именно пошагового ajax-скрипта, а не работы с CSV. Для работы с CSV вполне достаточно примера, описанного в посте Антона Долганина по ссылке в начале моего поста
безоговорочно верю в то, что раз существует в ядре битрикса специальный класс для выполнения какой-либо операции, значит что-то в этом классе сделано более качественно, или более понятно для битрикса, просто я еще не знаю, что именно.
А вообще, свой вопрос можете задать Антону Долганину по ссылке в начале моего поста У него опыта и знаний в данной области побольше, так что сможет дать более аргументированный ответ (я тоже почитаю:))
Попович Алексей написал: безоговорочно верю в то, что раз существует в ядре битрикса специальный класс для выполнения какой-либо операции, значит что-то в этом классе сделано более качественно, или более понятно для битрикса, просто я еще не знаю, что именно.
совсем нет вся суть bitrix - наплодить 100000 файлов чтобы работало только на дорогом хостинге без ограничений на кол-во файлов и процессорного времени
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».