Chamar seleção de arquivo(s) via JavaScript ou TypeScript (sem ter que clicar em input)

Em aplicações web é comum existir a necessidade de pedir para que o usuário selecione um ou mais arquivos. O jeito mais fácil de fazer isso é utilizando o elemento input com type=”file”, mas isso obriga que o usuário clique no respectivo componente renderizado.

Muitas vezes a proposta da aplicação que você está desenvolvendo pede um UX diferente desse padrão do browser.

Para poder chamar a janela de seleção de arquivos programaticamente via JavaScript ou TypeScript, sem a necessidade de clique do usuário, eu fiz essa função:

function selectFiles(multiple) {
    return new Promise(function (resolve) {
        const input = document.createElement('input');
        input.setAttribute('type', 'file');
        if (multiple) {
            input.setAttribute('multiple', 'multiple');
        }
        input.addEventListener('change', function (e) {
            const fileList = [];
            for (const file of e.target.files) {
                fileList.push(file)
            }
            resolve(fileList);
            input.remove();
        });
        input.click();
    });
}
const selectFiles = (multiple = false): Promise<File[]> => {
    return new Promise(resolve => {
        const input = document.createElement('input');
        input.setAttribute('type', 'file');
        if (multiple) {
            input.setAttribute('multiple', 'multiple');
        }
        input.addEventListener('change', (e: any) => {
            const fileList: File[] = [];
            for (const file of e.target.files) {
                fileList.push(file)
            }
            resolve(fileList);
            input.remove();
        });
        input.click();
    });
}

A função retornar uma promise de um array de files. O único parâmetro é um booleano com padrão false que indica se serão múltiplos arquivos.

A utilização fica assim:

  // Teste com async / await 
  async test1() {
    const fileList = await selectFiles();
    for (const file of fileList) {
      console.log(file.name);
    }
  }

  // Teste sem async / await 
  test2() {
    selectFiles().then(fileList => {
      for (const file of fileList) {
        console.log(file.name);
      }
    });
  }

Espero que isso ajude alguém!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *