JavaScript: Еще один вариант загрузки файла по клику на кнопку

Общая идея следующая: по клику на кнопку вызываем AJAX запрос на сервер с определенными параметрами передаваемыми в POST, затем получив в результат запроса файл — формируем в DOM на файл в формате blob, и тут-же её нажимаем. В результате браузер показывает диалоговое окно сохранения файла.

Таким необычным способом мы убиваем несколько зайцев сразу:

  1. Получаем возможность показать ошибку, если вдруг файл на сервере сформировать не удалось. Это полезно если например файл формируется на сервере «на лету» — например файл XLSX с отчётом
  2. Мы можем передать серверу какие-то условия для формирования файла в POST запросе
  3. На странице мы не размещаем заранее данные в тегах <form></form>, как практикуется в подобных решениях
  4. Пользователю достаточно нажать на кнопку один раз для получения результата.

В результате скрипт формирования файла может выглядеть примерно следующим образом:

На клиенте:

/**
 * Формирование отчета
 * @param {type} filename - имя файла на сервере для формирования отчета
 * @param {type} ext - выходное расширение (например xlsx,csv)
 * @returns {Number}
 */
function get_report(filename,ext){
        $("#global").addClass("loading");    
        var xhr = new XMLHttpRequest();
        xhr.open('POST', '?r=reports/'+filename, true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        xhr.responseType = 'blob';     
        xhr.onload = function(e) {
            $("#global").removeClass("loading");    
            if (this.status == 200) {
                var link=document.createElement('a');
                link.href=window.URL.createObjectURL(this.response);                
                console.log("Расширение:"+ext);
                link.download="report."+ext;
                link.click();
            }
            else {
                console.log(e);
                ToastMessage("error","Произошла ошибка при формировании файла. Попробуйте позднее или обратитесь к администратору системы.");
            }
        };     
        var form_data = new Map();
        form_data.period_from = period_from.value;
        form_data.period_to = period_to.value;
        form_data.area = area_select.value;
        form_data.division_check=division_check.checked;
        form_data.period_check=period_check.checked;
        xhr.send(mapToQueryString(form_data));                                          
};

На сервере:

    public function actionGet_report_by_settlers(){               
       $request = Yii::$app->request;      
       $area= $request->post("area");
       $dir=Yii::$app->basePath."/web/templates";
        
      $oSpreadsheet = IOFactory::load($dir . "/report_1_1.xlsx");
      ...
      формируем файл эксель
      ...
      $oWriter = IOFactory::createWriter($oSpreadsheet, 'Xlsx');
      $oWriter->save('php://output');      
    };

Консоль администрирования 1С под Linux

Перейдя с Windows на Linux, теряется возможность управлять сервером 1С Предприятие через консоль администрирования, через оснастку. Но! оказывается довольно давно уже в платформе зашита подобная же утилита, которая доступна через «Функции для технического специалиста»: Стандартные -> Управление серверами.

При запуске будет практически аналогичная функциональность доступная ранее через консоль:

Чтиво за последнее время

  1. Андрей Ланченко. Блуждающие огни 1-4. Краткий сюжет: земля на задворках, и оказывается она забытая колония. Программист Дима через портал попал на транспортный корабль колонистов. И понеслось (с). Читабельность 4/5
  2. Григорий Володин. Газлайтер 1-18. Классическое бояр-аниме. Попаданец в паралельный мир с магией и прочим. Там не было СССР и власть в руках дворян/царя. Читабельность 4/5
  3. Толкиню Хоббит. Властелин колец. Дочке не зашло, хотя прочитали примерно половину.
чтиво за последнее время

1С: Фоновые задания внутри фоновых заданий

Задача: распаралелить медленную вставку записей в БД 1С, при чтении файла Excel

Как ни странно, но такая возможность есть и работает начиная с версии платформы 8.3.8. Т.е. можно запустить фоновое задание внутри фонового задания….ну например по вставке в БД большого количества записей, которая выполняется весьма медленно. Полноценно этот процесс распаралелить можно например как-то так:

Функция СделатьЗаписьвБДПДЗФоново(парам) экспорт
	...
    // делаем медленную запись в БД
	...
конецфункции	

// Просматриваем массив с идентификаторами фоновых заданий и удаляем те которые завершились
Функция ПочиститьМассивОтЗавершенныхЗаданий(МассивФоновыхЗаданий) экспорт
		для каждого ФЗМ из МассивФоновыхЗаданий цикл
			ФЗ = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ФЗМ);
			если ФЗ.Состояние<>СостояниеФоновогоЗадания.Активно тогда
				МассивФоновыхЗаданий.Удалить(МассивФоновыхЗаданий.Найти(ФЗМ));
			конецесли;	
		конеццикла;		
	возврат МассивФоновыхЗаданий;
конецфункции		

// выполняем загрузку построчно файла Excel, запуская запись данных в БД
// отдельным потоком. Количество потоков ограничивам 10 штуками
Функция ВыполнитьЗагрузку(парам) экспорт
	МассивФоновыхЗаданий=Новый Массив();
	МаксимумЗаданий=10;
...
    Для	 нСтрокаТФ = 2 ПО КолВоСтрокФайла Цикл  
        ....
			МассивПараметров = Новый Массив;
			Параметры=Новый Структура("aa,bb,cc",
				1,
				2,
				3,
            );
			МассивПараметров.Добавить(Параметры);
			ФЗ = ФоновыеЗадания.Выполнить("ДлительныеОперации.СделатьЗаписьвБДПДЗФоново",МассивПараметров);	
			МассивФоновыхЗаданий.Добавить(ФЗ.УникальныйИдентификатор);											
			МассивФоновыхЗаданий=ПочиститьМассивОтЗавершенныхЗаданий(МассивФоновыхЗаданий);
			// ждём пока завершаться запущеные потоки, если их больше 10
			пока МассивФоновыхЗаданий.Количество()>МаксимумЗаданий цикл
				МассивФоновыхЗаданий=ПочиститьМассивОтЗавершенныхЗаданий(МассивФоновыхЗаданий);
			конеццикла;	        
        ....
   конеццикла;
конецфункции	   

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

Сложение с null в запросе

Иногда удаётся найти подводные камни там, где совсем не ждешь от 1С. Оказывается в запросах 1С, сложение столбцов а+б даёт в сумме null, если одно из значений равно null. даже если чётко укажешь преобразовать значение в строку, например так:

строка(geo_coors_public_regions.name)+строка(geo_coors_public_areas.name)

Не прокатывает (с). Приходится городить код вида:

ВЫБОР
		КОГДА geo_coors_public_regions.name ЕСТЬ NULL
			ТОГДА ""
		ИНАЧЕ geo_coors_public_regions.name
	КОНЕЦ + "," + ВЫБОР
		КОГДА geo_coors_public_areas.name ЕСТЬ NULL
			ТОГДА ""
		ИНАЧЕ geo_coors_public_areas.name
	КОНЕЦ + "," + ВЫБОР
		КОГДА geo_coors_public_cities.name ЕСТЬ NULL
			ТОГДА ""
		ИНАЧЕ geo_coors_public_cities.name
	КОНЕЦ + "," + ВЫБОР
		КОГДА geo_coors_public_settlers.name ЕСТЬ NULL
			ТОГДА ""
		ИНАЧЕ geo_coors_public_settlers.name
	КОНЕЦ
ИЗ
...

1 16 17 18 19 20 310