Стандартный диалог выбора файлов в веб интерфейсе


  • administrators

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

    А ещё @support запланировал немного изменить диалог выбора файла:


    Есть несколько причин, почему @support сделал кастомную реализацию выбора файла:

    @support said in Конструктор интерфейса.:

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

    Так же браузер не позволяет получить путь к файлу. Поэтому придется пересылать в BAS содержание файла. Это не очень удобно.
    Вместо этого используется своя реализация, но вы можете использовать и системный диалог, для этого его просто нужно прописать в коде. Здесь пример, как это можно сделать https://wiki.bablosoft.com/web-interface/#/codeeditor?id=adding-custom-components



    По этому единственный способ передать содержимое файла в скрипт через стандартный диалог выбора файла, это прочитать файл в веб интерфейсе через File API и перенести содержимое в ресурс с типом "строка". Вариант с передачей содержимого файла через глобальную переменную или базу я расскажу в следующий раз.


    Для начала создадим проект и добавим в него ресурс file с типом "строка"
    0_1560630005338_b09d7bad-61f0-48c4-bf26-8225997abb64-изображение.png

    выгрузим проект на сервер bablosoft и сгенерируем интерфейс скрипту:
    0_1560630223096_9f6c6f0a-bddc-4754-a200-acae4400c989-изображение.png

    Далее надо создать простой input для выбора файла в любом удобном для вас месте:

    <input type="file"/>
    

    0_1560630997962_a77c9a05-2283-4fc2-8504-56cdc565a3d2-изображение.png


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

    <div class="table-row" hidden="true">
    

    0_1560631364983_949ac448-5e8f-4a83-a3e8-2d8dd77d2d561-изображение.png


    Затем находим строку /////Events в окне Javascript и создаём обработчик события с чтением файла в переменную:

    $("input:file").change(function(){
                    var reader = new FileReader();
                    reader.onload = function (e) {  
                        res = e.target.result;
                    };
                    reader.readAsText(this.files[0]);
            }) 
    });
    

    следом находим функцию GetResourceValue, она идёт тремя строками ниже, и добавляем в неё условие для ресурса file

    var res = ""//объявляем переменную чтобы небыло ошибки, если пользователь не укажет файл и запустит скрипт.
    function GetResourceValue(ResourceName){
        if(ResourceName == "file"){
        return res
        }
        return GetValue(ResourceName)
    }
    

    0_1560634186885_87972735-5640-4bf2-a99a-8fba16f820da-изображение.png

    В скрипте всего два действия:
    0_1560632750716_69444a51-f23e-4f9f-b719-b444c260f59b-изображение.png

    Вот так выглядит результат:

    0_1560632776733_support84.gif


    Самый простой вариант применения, это в функции OnApplicationStart распарсить строку по переносу строк \r\n в массив и перенести его в локальный ресурс, чтобы в скрипте использовать как обычный ресурс:

    0_1560633082806_76499872-6c1b-4df7-8140-845d093a5241-изображение.png



    Тестовый скрипт
    и экспортированный интерфейс


  • administrators

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

    <input type="file" multiple/>
    

    изменить обработчик события для input:

    $("input:file").change(function () {
        for (var i = 0; i < this.files.length; i++) {
            var reader = new FileReader();
            reader.onload = function (e) {
                res = res + e.target.result + "\r\n";
            }
            reader.readAsText(this.files[i]);
    
        }
    }) 
    

    функция GetResourceValue() остаётся такой же:

    var res = ""
    function GetResourceValue(ResourceName){
        if(ResourceName == "file"){
        return res
        
        }
        return GetValue(ResourceName)
    }
    

    результат:

    Экспортированный интерфейс


  • administrators

    А вот загружать файлы в скрипт через Drag and drop выглядит уже по приличнее:

    0_1560647352711_99794378-fafc-4ebf-967c-7c8f9813947c-изображение.png
    0_1560647368126_c658b3fa-19db-4c8a-873f-e318e7937f71-изображение.png

    html

    <div id="drop_file" align="center" >Перетащите сюда файлы</div>
    

    css

    #drop_file {
      border: 2px dashed #ccc;
      border-radius: 20px;
      width: 280px;
      font-family: sans-serif;
      margin: 20px auto;
      padding: 20px;
    }
    #drop_file.highlight {
      border-color: purple;
    }
    

    js

      function handleFileSelect(evt) {
        evt.stopPropagation();
        evt.preventDefault();
    
        var files = evt.dataTransfer.files;
    
        var output = [];
        for (var i = 0, f; f = files[i]; i++) {
          output.push(escape(f.name));
            var reader = new FileReader();
            reader.onload = function (e) {
                res = res + e.target.result + "\r\n";
            }
            reader.readAsText(f);
        }
        $("#drop_file").text(output.join(', '))
      }
    
      function handleDragOver(evt) {
        $("#drop_file").addClass('highlight')
        evt.stopPropagation();
        evt.preventDefault();
        evt.dataTransfer.dropEffect = 'copy';
      }
    
      var drop_file= document.getElementById('drop_file');
      drop_file.addEventListener('dragover', handleDragOver, false);
      drop_file.addEventListener('drop', handleFileSelect, false);
    

    Без минимального оформления можно было сделать, но выглядело это всё ужасно. А так, хоть готовый вариант для ленивых :D

    Результат:

    0_1560647224064_support87.gif

    Экспортированный интерфейс



  • Кастомный интерфейс по умолчанию имеет uikit, благодаря которому можно изменять вид формы ввода файла так как вы захотите, просто поместив <input type="file"> в контейнер с атрибутом uk-form-custom подробнее в документации ukit

    Пример:

    <div uk-form-custom="target: true">
        <input type="file">
        <input class="uk-input uk-form-width-medium" type="text" placeholder="Select file" disabled>
        <button class="uk-button uk-button-default" type="button">Select</button>
    </div>
    

    Результат:
    0_1560694250463_ea81521d-dda0-4f23-8a24-5ec6526af129-image.png
    0_1560694285221_9dfb5e58-92bf-4c9d-ab87-3d6fb5a873cf-image.png
    При нажатии на поле или кнопку открывается окно с выбором файла



  • Drag and drop тоже там есть
    https://getuikit.com/docs/upload#drop-area



  • Возможно ли с помощью стандартного диалога указать путь до папки, (например куда будут сохраняться файлы)?!


  • administrators

    @boltzzzz said in Стандартный диалог выбора файлов в веб интерфейсе:

    Возможно ли с помощью стандартного диалога указать путь до папки, (например куда будут сохраняться файлы)?!

    Нет, я же в первом сообщении об этом писал:
    0_1560710785726_8ca701c9-b28c-4868-8288-0dcbd877d4ee-изображение.png

    возможно только указать путь в виде строки



  • Объясните пожалуйста что и куда нужно вставить в этом коде что бы список начал подхватываться (пытаюсь настроить стандартный диалог выбора файла)* , у меня не получается...

    В скрипте который описывается тут (создал отдельно)* - работает

    Основной код моего скрипта который не могу настроить

    										<div uk-alert="" data-resource-name="Добавить файл5" data-resource-type="LinesFromFile" data-visibility-condition-value="Подписаться по списку" data-visibility-condition-variable="Выбрать способ" data-default-value="">
    											<div class="resource-label">Что будем делать</div>
    											<div class="server-side-file-dialog" id="iepqkn">
    												<input type="text" placeholder="Path to file" validation-file="true" tab-index="3" value="" class="uk-input ui-internal" id="iascfg">
    												<button class="uk-button uk-button-default ui-internal" id="i12vv2">
    													<span uk-icon="file-edit"></span>
    												</button>
    											</div>
    										</div>
    

    в JS в Events . указал как предлогается выше

        /////Events
    
        $("input:file").change(function() {
            var reader = new FileReader();
            reader.onload = function(e) {
                res = e.target.result;
            };
            reader.readAsText(this.files[0]);
        })
    
    });
    var res
    
    /////Resource values are obtained through this function when hitting run button, you can change it.
    /////For example, you can edit value entered by user, make custom validation, or replace resource system compleatelly
    
    function GetResourceValue(ResourceName) {
        if (ResourceName == "file") {
            return res
        }
        return GetValue(ResourceName)
    }
    

    Пробовал изменять свой основной код подобными вариациями

    <div uk-alert="" uk-form-custom="target: true" data-resource-name="Добавить файл6" data-resource-type="LinesFromFile" data-visibility-condition-value="Лайкнуть по списку" data-visibility-condition-variable="Выбрать способ" data-default-value="">
    <input type="file">
    <input class="uk-input uk-form-width-large" type="text" placeholder="Выбрать файл" disabled>
    <button class="uk-button uk-button-default">Нажать</button>
    </div>
    

    К сожалению не работает, подскажите пожалуйста как сделать?


  • administrators

    @boltzzzz said in Стандартный диалог выбора файлов в веб интерфейсе:

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

    В скрипте который описывается тут (создал отдельно)* - работает
    К сожалению не работает, подскажите пожалуйста как сделать?

    В функции GetResourceValue() в условии нужно указывать название своего ресурса:

    function GetResourceValue(ResourceName) {
        if (ResourceName == "имя своего ресурса") {
            return res
        }
        return GetValue(ResourceName)
    }
    

    Так же тип ресурса должен быть "строка" а не "из файла" (data-resource-type="LinesFromFile")



  • @fox
    HTML

                                            <div uk-alert="" uk-form-custom="target: true" data-resource-name="Добавить файл6" data-resource-type="FixedString" data-visibility-condition-value="Лайкнуть по списку" data-visibility-condition-variable="Выбрать способ" data-default-value="">
    											<input type="file">
    											<input type="text" placeholder="Выбрать файл" disabled="" class="uk-input uk-form-width-large">
    											<button class="uk-button uk-button-default">Нажать</button>
    										</div>
    

    JS

        /////Events
    
        $("input:file").change(function() {
            var reader = new FileReader();
            reader.onload = function(e) {
                res = e.target.result;
            };
            reader.readAsText(this.files[0]);
        })
    
    });
    var res
    
    /////Resource values are obtained through this function when hitting run button, you can change it.
    /////For example, you can edit value entered by user, make custom validation, or replace resource system compleatelly
    
    function GetResourceValue(ResourceName) {
        if (ResourceName == "Добавить файл6") {
            return res
        }
        return GetValue(ResourceName)
    

    Всё равно не подхватывает, что сделал: заменил на строку (data-resource-type="FixedString"), добавил имя ресурса в JS



  • @boltzzzz

    <div uk-alert="" uk-form-custom="target: true" data-visibility-condition-value="Лайкнуть по списку" data-visibility-condition-variable="Выбрать способ" data-default-value="">
    <input type="file">
    <input type="text" placeholder="Выбрать файл" disabled="" class="uk-input uk-form-width-large">
    <button class="uk-button uk-button-default">Нажать</button>
    </div>
    
    <div uk-alert="" data-resource-name="Добавить файл6" data-resource-type="FixedString" data-default-value=""  hidden="true">
    <input type="text" placeholder="" value="" class="uk-input">
    </div>
    


  • @ghostz Способ не работает(


  • administrators

    @boltzzzz said in Стандартный диалог выбора файлов в веб интерфейсе:

    @ghostz Способ не работает(

    Способ работает, скорее всего вы допустили где то ошибку. Хоть и разжевано всё с примерами, скриншотами и готовыми вариантами.

    Что бы ещё 12 дней не ждать, сгенерируйте новый интерфейс для своего скрипта
    0_1561788209227_ecedc5b8-a913-4f08-800c-131c3b75a268-изображение.png

    затем экспортируйте его в файл
    0_1561788291793_ca288533-107f-49ee-9f5c-25637dfc1de7-изображение.png

    и выложите сюда
    0_1561788332245_b2ee1022-1b3a-4ded-b1d9-608220126b74-изображение.png




  • Drag and drop выглядит симпатично. Вообще стандартный обозреватель файлов хоть на вид и минималистичен и вписывается в любой дизайн, очень неудобен в обращении. Прочти я эту статью годиком раньше, у меня бы не кипела голова в поисках решений. Хотя, как уже правильно ответили выше, решение очень простое, всего лишь нужно поиграться с uikit.