Infinity8 Infinity8 - 2 months ago 19
HTML Question

Folder picker in HTML with Flask for Uploads

I am running a Flask app where the user uploads a file and must select the root folder path of where to upload the file on a network drive. This path is an IIS available network path and is also a network drive on all user's computers.

I know this can't be done with pure HTML due to security but wanted to know if there was a way around this with Flask. The goal is to use Python to move the upload file to the choosen folder path.

I have tried:

<form><input type="file" name=dir webkitdirectory directory multiple/></form>


But this only works in Chrome. With the path choosen by the user I can pass this onto Python to copy the upload file to there.

Answer

Due to modern browser limitations I decided to use JSTree as a solution. And it is working very well. It features a tree structure browser. The structure is the result of outputting the folders as JSON. You can add a search bar as well so the user can just type in a folder name to search.
Please see JSTree https://www.jstree.com/

How to implement this with Flask

HTML/JS:

  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css">
  <div>
  <input class="search-input form-control" placeholder="Search for folder"></input>
  </div>
<script id="jstree1" name="jstree1">
                        /*Search and JS Folder Tree*/
                        $(function () {
                            $(".search-input").keyup(function () {
                                var searchString = $(this).val();
                                console.log(searchString);
                                $('#container').jstree('search', searchString);
                            });
                            $('#container').jstree({
                                'core': {
                                    "themes": {
                                        "name": "default"
                                        , "dots": true
                                        , "icons": true
                                    }
                                    , 'data': {
                                        'url': "static/JSONData.json"
                                        , 'type': 'GET'
                                        , 'dataType': 'JSON'
                                    }
                                }
                                , "search": {
                                    "case_insensitive": true
                                    , "show_only_matches": true
                                }
                                , "plugins": ["search"]
                            });
                        });

                        { /*  --- THIS IS FOLDER SELECTOR FOR ID "folderout" --- */
                            $("#container").on("select_node.jstree", function (evt, data) {
                                var number = data.node.text

                                document.getElementById("folderout").value = number;
                            });

In Flask/WTForms call on the id "folderout". This will return the path to WTForms when the user clicks the folder.

folderout = TextField('Folder:', validators=[validators.required()])

To Create the JSON JStree File using Python:

import os

# path   : string to relative or absolute path to be queried
# subdirs: tuple or list containing all names of subfolders that need to be
#          present in the directory
def all_dirs_with_subdirs(path, subdirs):
    # make sure no relative paths are returned, can be omitted
    path = os.path.abspath(path)

    result = []
    for root, dirs, files in os.walk(path):
        if all(subdir in dirs for subdir in subdirs):
                result.append(root)
    return result

def get_directory_listing(path):
    output = {}
    output["text"] = path.decode('latin1')
    output["type"] = "directory"
    output["children"] = all_dirs_with_subdirs(path, ('Maps', 'Reports'))
    return output

with open('test.json', 'w+') as f:
    listing = get_directory_listing(".")
    json.dump(listing, f)