Fazer upload de arquivos do Formulários Google para o Drive

Nível de programação: iniciante
Duração: 10 minutos
Tipo de projeto: automação com um gatilho orientado a eventos

Objetivos

  • Entenda o que a solução faz.
  • Entenda o que os serviços do Apps Script fazem na solução.
  • Configure o script.
  • Execute o script.

Sobre esta solução

Faça upload e organize arquivos simultaneamente no Google Drive usando os Formulários Google. O formulário inclui entradas para os arquivos a serem enviados e para como eles devem ser organizados.

Captura de tela do formulário para fazer upload de arquivos

Como funciona

Uma função de configuração cria uma pasta para armazenar todos os arquivos enviados por upload e um gatilho que é ativado sempre que alguém envia o formulário. Durante o processo de preencher o formulário, o usuário escolhe quais arquivos enviar e em qual subpasta eles serão armazenados. Depois disso, o script direciona os arquivos para a subpasta correta. Se a pasta ainda não existir, o script vai criar uma.

Serviços do Apps Script

Esta solução usa os seguintes serviços:

  • Serviço de script: cria o gatilho que é ativado sempre que alguém envia o formulário.
  • Serviço de propriedades: armazena o ID do acionador que o script cria durante a configuração para evitar acionadores duplicados.
  • Serviço do Drive: durante a configuração, ele recebe a localização do formulário no Drive e cria uma pasta no mesmo local. Quando um usuário envia o formulário, o serviço do Drive direciona os arquivos para essa pasta e, se selecionada, para uma subpasta designada. Se a subpasta ainda não existir, o script vai criar uma.
  • Serviço do Formulários: recebe os arquivos e o nome da pasta escolhidos pelo usuário depois que ele envia o formulário e os envia para o serviço do Drive.

Pré-requisitos

Para usar esta amostra, você precisa atender aos seguintes pré-requisitos:

  • Uma Conta do Google (as contas do Google Workspace podem exigir a aprovação do administrador).
  • Um navegador da Web com acesso à Internet.

Configurar o script

Criar o formulário

  1. Acesse forms.google.com e clique em Em branco .
  2. Clique em Formulário sem título e renomeie o formulário como Fazer upload de arquivos para o Drive.
  3. Clique em Pergunta sem título e renomeie a pergunta como Subpasta.
  4. Na pergunta Subpasta, clique em Mais > Descrição.
  5. Em Descrição, digite Selecione a subpasta para armazenar seus arquivos. Se você selecionar <Nenhum>, os arquivos serão armazenados na pasta "Arquivos enviados".
  6. Adicione as seguintes opções à pergunta Subpasta:
    • <none>
    • Projeto A
    • Projeto B
    • Projeto C
  7. Para tornar a pergunta obrigatória, clique em Obrigatória.
  8. Clique em Adicionar pergunta .
  9. Clique em Múltipla escolha e selecione Upload de arquivo.
  10. Clique em Continuar.
  11. Em Pergunta, insira Arquivos para upload. Você pode escolher os tipos de arquivo e o número máximo de arquivos que as pessoas podem enviar por upload.
  12. Para tornar a pergunta obrigatória, clique em Obrigatória.

Criar o projeto do Apps Script

  1. No formulário, clique em Mais > Editor de script.
  2. Clique em Projeto sem título e renomeie o projeto como Fazer upload de arquivos para o Drive.
  3. Para criar outro arquivo de script, clique em Adicionar um arquivo > Script. Nomeie o arquivo Setup.
  4. Substitua o conteúdo dos dois arquivos de script pelo seguinte:

    Code.gs

    solutions/automations/upload-files/Code.js
    // TODO Before you start using this sample, you must run the setUp() 
    // function in the Setup.gs file.
    
    // Application constants
    const APP_TITLE = "Upload files to Drive from Forms";
    const APP_FOLDER_NAME = "Upload files to Drive (File responses)";
    
    // Identifies the subfolder form item
    const APP_SUBFOLDER_ITEM = "Subfolder";
    const APP_SUBFOLDER_NONE = "<None>";
    
    
    /**
     * Gets the file uploads from a form response and moves files to the corresponding subfolder.
     *  
     * @param {object} event - Form submit.
     */
    function onFormSubmit(e) {
      try {
        // Gets the application root folder.
        var destFolder = getFolder_(APP_FOLDER_NAME);
    
        // Gets all form responses.
        let itemResponses = e.response.getItemResponses();
    
        // Determines the subfolder to route the file to, if any.
        var subFolderName;
        let dest = itemResponses.filter((itemResponse) =>
          itemResponse.getItem().getTitle().toString() === APP_SUBFOLDER_ITEM);
    
        // Gets the destination subfolder name, but ignores if APP_SUBFOLDER_NONE was selected;
        if (dest.length > 0) {
          if (dest[0].getResponse() != APP_SUBFOLDER_NONE) {
            subFolderName = dest[0].getResponse();
          }
        }
        // Gets the subfolder or creates it if it doesn't exist.
        if (subFolderName != undefined) {
          destFolder = getSubFolder_(destFolder, subFolderName)
        }
        console.log(`Destination folder to use:
        Name: ${destFolder.getName()}
        ID: ${destFolder.getId()}
        URL: ${destFolder.getUrl()}`)
    
        // Gets the file upload response as an array to allow for multiple files.
        let fileUploads = itemResponses.filter((itemResponse) => itemResponse.getItem().getType().toString() === "FILE_UPLOAD")
          .map((itemResponse) => itemResponse.getResponse())
          .reduce((a, b) => [...a, ...b], []);
    
        // Moves the files to the destination folder.
        if (fileUploads.length > 0) {
          fileUploads.forEach((fileId) => {
            DriveApp.getFileById(fileId).moveTo(destFolder);
            console.log(`File Copied: ${fileId}`)
          });
        }
      }
      catch (err) {
        console.log(err);
      }
    }
    
    
    /**
     * Returns a Drive folder under the passed in objParentFolder parent
     * folder. Checks if folder of same name exists before creating, returning 
     * the existing folder or the newly created one if not found.
     *
     * @param {object} objParentFolder - Drive folder as an object.
     * @param {string} subFolderName - Name of subfolder to create/return.
     * @return {object} Drive folder
     */
    function getSubFolder_(objParentFolder, subFolderName) {
    
      // Iterates subfolders of parent folder to check if folder already exists.
      const subFolders = objParentFolder.getFolders();
      while (subFolders.hasNext()) {
        let folder = subFolders.next();
    
        // Returns the existing folder if found.
        if (folder.getName() === subFolderName) {
          return folder;
        }
      }
      // Creates a new folder if one doesn't already exist.
      return objParentFolder.createFolder(subFolderName)
        .setDescription(`Created by ${APP_TITLE} application to store uploaded Forms files.`);
    }

    Setup.gs

    solutions/automations/upload-files/Setup.js
    // TODO You must run the setUp() function before you start using this sample.
    
    /** 
     * The setUp() function performs the following:
     *  - Creates a Google Drive folder named by the APP_FOLDER_NAME
     *    variable in the Code.gs file.
     *  - Creates a trigger to handle onFormSubmit events.
     */
    function setUp() {
      // Ensures the root destination folder exists.
      const appFolder = getFolder_(APP_FOLDER_NAME);
      if (appFolder !== null) {
        console.log(`Application folder setup.
        Name: ${appFolder.getName()}
        ID: ${appFolder.getId()}
        URL: ${appFolder.getUrl()}`)
      }
      else {
        console.log(`Could not setup application folder.`)
      }
      // Calls the function that creates the Forms onSubmit trigger.
      installTrigger_();
    }
    
    /** 
     * Returns a folder to store uploaded files in the same location
     * in Drive where the form is located. First, it checks if the folder
     * already exists, and creates it if it doesn't.
     *
     * @param {string} folderName - Name of the Drive folder. 
     * @return {object} Google Drive Folder
     */
    function getFolder_(folderName) {
    
      // Gets the Drive folder where the form is located.
      const ssId = FormApp.getActiveForm().getId();
      const parentFolder = DriveApp.getFileById(ssId).getParents().next();
    
      // Iterates through the subfolders to check if folder already exists.
      // The script checks for the folder name specified in the APP_FOLDER_NAME variable.
      const subFolders = parentFolder.getFolders();
      while (subFolders.hasNext()) {
        let folder = subFolders.next();
    
        // Returns the existing folder if found.
        if (folder.getName() === folderName) {
          return folder;
        }
      }
      // Creates a new folder if one doesn't already exist.
      return parentFolder.createFolder(folderName)
        .setDescription(`Created by ${APP_TITLE} application to store uploaded files.`);
    }
    
    /**
     * Installs trigger to capture onFormSubmit event when a form is submitted.
     * Ensures that the trigger is only installed once.
     * Called by setup().
     */
    function installTrigger_() {
      // Ensures existing trigger doesn't already exist.
      let propTriggerId = PropertiesService.getScriptProperties().getProperty('triggerUniqueId')
      if (propTriggerId !== null) {
        const triggers = ScriptApp.getProjectTriggers();
        for (let t in triggers) {
          if (triggers[t].getUniqueId() === propTriggerId) {
            console.log(`Trigger with the following unique ID already exists: ${propTriggerId}`);
            return;
          }
        }
      }
      // Creates the trigger if one doesn't exist.
      let triggerUniqueId = ScriptApp.newTrigger('onFormSubmit')
        .forForm(FormApp.getActiveForm())
        .onFormSubmit()
        .create()
        .getUniqueId();
      PropertiesService.getScriptProperties().setProperty('triggerUniqueId', triggerUniqueId);
      console.log(`Trigger with the following unique ID was created: ${triggerUniqueId}`);
    }
    
    /**
     * Removes all script properties and triggers for the project.
     * Use primarily to test setup routines.
     */
    function removeTriggersAndScriptProperties() {
      PropertiesService.getScriptProperties().deleteAllProperties();
      // Removes all triggers associated with project.
      const triggers = ScriptApp.getProjectTriggers();
      for (let t in triggers) {
        ScriptApp.deleteTrigger(triggers[t]);
      }
    }
    
    /**
     * Removes all form responses to reset the form.
     */
    function deleteAllResponses() {
      FormApp.getActiveForm().deleteAllResponses();
    }

Executar o script

  1. No editor do Apps Script, mude para o arquivo Setup.gs.
  2. No menu suspenso de funções, selecione setUp.
  3. Clique em Executar.
  4. Quando solicitado, autorize o script. Se a tela de permissão OAuth mostrar o aviso Este app não foi verificado, selecione Avançado > Acessar {Nome do projeto} (não seguro).

  5. Volte ao formulário e clique em Visualizar Ícone de visualização.

  6. No formulário, selecione uma subpasta e faça upload de um arquivo.

  7. Clique em Enviar.

  8. Acesse o Drive e abra a pasta Fazer upload de arquivos para o Drive (respostas do arquivo). Os arquivos enviados estão na subpasta selecionada no formulário.

Colaboradores

Esta amostra é mantida pelo Google com a ajuda dos Google Developer Experts.

Próximas etapas