Preview all the contents of a specified folder online using ArrayBuffer

This is the 9th day of my participation in Gwen Challenge

The effect

The renderings are very simple, no code highlighting plugins, no style sheets

  • Full instance source code

What is the ArrayBuffer

An ArrayBuffer represents a chunk of memory that stores binary data. It cannot be read or written directly, but can only be read or written through views (TypedArray and DataView views) that interpret binary data in a specified format.

The goods are relatively hard, so I will not introduce them in detail here, and I will introduce the use of these hard goods through examples

  • ECMAScript 6 – ArrayBuffer Objects is recommended

Reading file contents

  1. Through the use ofFileReader.readAsArrayBufferMethod will beFileObject toArrayBuffer
  2. useTextDecoderConvert content toutf8Formatted text
function readFile2Text(file) {
    const fileReader = new FileReader()
    fileReader.readAsArrayBuffer(file)
    return new Promise(resolve= >{
        fileReader.onload = function () {
            const buf = this.result
            const textDecoder = new TextDecoder('utf8')
            resolve(textDecoder.decode(buf))
        }
    })
}
Copy the code

You can also use filereader.readastext directly

Forcing readAsArrayBuffer to fit the theme

function readFile2Text(file) {
    const fileReader = new FileReader()
    fileReader.readAsText(file)
    return new Promise(resolve= >{
        fileReader.onload = function () {
            resolve(this.result)
        }
    })
}
Copy the code

Reads all files in the specified directory

MDN:

  • Webkitdirectory: Only directories can be selected
  • Multiple: Allows you to select multiple files

Page code

<input type="file" id="file" webkitdirectory multiple>
Copy the code

Listen for the DOM onchange event to get all selected files (excluding empty directories)

logic

const $file = document.getElementById('file')

// Select a directory
$file.onchange = function () {
    const files = this.files
    // Print to get all the files
    console.log(files)
}
Copy the code

Each file object contains the following properties

{
    name: String./ / file
    size: Number.// File size
    type: String.// File MIME type
    webkitRelativePath: String.// File relative path
}
Copy the code

Tree directory generation

Use UL and LI to achieve

Dom structure

<div id="lists" style="width: 36%;">
    <ul>
        <li path="test" deep="0">test
            <ul>
                <li path="test/logo.jpeg" deep="1">logo.jpeg</li>
                <li path="test/1" deep="1">1
                    <ul>
                        <li path="test/1/1-2" deep="2">1 to 2<ul>
                                <li path="test/1/1-2/index.js" deep="3">index.js</li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>
Copy the code

show

  • test
    • logo.jpeg
    • 1
      • 1 to 2
        • index.js

The specific implementation

Page code

<input type="file" id="file" webkitdirectory multiple>
<div id="lists"></div>
Copy the code

logic

Js => [‘test’,’ ABC ‘,’index.js’]

const $file = document.getElementById('file')
const $lists = document.getElementById('lists')
// Select a directory
$file.onchange = function () {
    const files = this.files
    // Empty all
    $lists.innerHTML = ' '
    // Unpack the directory
    for (const f of files) {
        f.paths = f.webkitRelativePath.split('/')
    }
    appendDir($lists, files)
}
Copy the code

appendDir:

  • Parent: indicates the parent node
  • Files: files
  • Deep: indicates the directory depth

This method generates a directory for a specified level

function appendDir(parent, files, deep = 0) {
    const $ul = document.createElement('ul')
    // Use Set to store the common prefix for all files
    // use Set to automatically remove the weight
    const dirs = new Set(a)for (const f of files) {
        // Take a directory of the same depth
        const p = f.paths[deep]

        // Depth is 0, indicating the selected directory
        if (deep === 0) {
            dirs.add(p)
        } else {
            // Get the relative directory of the parent node
            const parentP = parent.getAttribute('path')
            // Determine whether the file belongs to the parent directory
            if (f.webkitRelativePath.startsWith(parentP)) {
                // Save the qualified file path
                dirs.add([parentP, p].join('/'))}}}// 
    for (const d of dirs) {
        const $li = document.createElement('li')

        // Display only the file name or directory name (test/ ABC /index.js => index.js)
        const idx = d.lastIndexOf('/') + 1
        $li.textContent = idx===0 ? d : d.slice(idx)

        // Record the depth and full relative path of this node
        $li.setAttribute('path', d)
        $li.setAttribute('deep', deep)
        $ul.appendChild($li)
    }
    // Insert the page
    if(dirs.size ! = =0) {
        parent.appendChild($ul)
    }
}
Copy the code

Listen for li’s click events using the event broker

$lists.addEventListener('click'.function (e) {
    const $li = e.target
    // It's not li that doesn't care
    if($li.tagName.toLowerCase() ! = ='li') {
        return
    }
    // Get the path and depth of the clicked node
    const path = $li.getAttribute('path')
    const deep = +$li.getAttribute('deep')

    // Get all the selected files
    const files = $file.files

    // Walk through the file to determine whether it is a file or a directory

    for (const f of files) {
        // Click the file
        if (f.webkitRelativePath === path) {
            // Preview the content
            previewFile(f)
            return}}// There are subitems, click the directory and have not been added by the click
    if ($li.children.length === 0) {
        appendDir($li, files, deep + 1)}})Copy the code

The generated directory looks like this:

The last

The contents of ArrayBuffer are still quite large, and this article only briefly describes how to use it to get the contents of files

The main content of this article is the practice of generating directory tree structure, due to the time is short, the code has a lot of room for optimization

The sample presentation is rough and very malleable