Saltar al contenido

Subir varios archivos a Google Drive con Google App Script

Solución:

Sé que esta pregunta es antigua, pero después de encontrarla y otras relacionadas, nunca pude hacer funcionar la carga de varios archivos. Entonces, después de mucho golpearme la cabeza contra las paredes, quería publicar un ejemplo completo (.html y .gs) en caso de que alguien en el futuro esté buscando uno para comenzar. Esto está funcionando cuando lo implemente en este momento y espero que funcione para otras personas. Tenga en cuenta que solo codifiqué la carpeta en la unidad para usarla en el archivo code.gs, pero eso se puede cambiar fácilmente.

form.html:

<body>
  <div>

    <label for="myForm">Facilities Project Database Attachment Uploader:</label>

    <br><br>


    <form> 
      <label for="myForm">Project Details:</label>
      <div>
        <input type="text" name="zone" placeholder="Zone:">
      </div>
      <div>
        <input type="text" name="building" placeholder="Building(s):">
      </div>
      <div>
        <input type="text" name="propertyAddress" placeholder="Property Address:">
      </div>
      <div>

      <label for="fileText">Project Description:</label>

          <TEXTAREA name="projectDescription" 
          placeholder="Describe your attachment(s) here:"
          style ="width:400px; height:200px;"
          ></TEXTAREA>


      </div> 
      <br>


      <label for="attachType">Choose Attachment Type:</label>
      <br>
      <select name="attachType">
        <option value="Pictures Only">Picture(s)</option>
        <option value="Proposals Only">Proposal(s)</option>
        <option value="Pictures & Proposals">All</option>
      </select>
      <br>

      <label for="myFile">Upload Attachment(s):</label>
      <br>


      <input type="file" name="filename" multiple>

      <input type="button" value="Submit" onclick="iteratorFileUpload()">


    </form>
  </div>

  <div></div>
<div>
    <div></div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

<script>

var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;

// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
    var allFiles = document.getElementById('myFile').files;

    if (allFiles.length == 0) {
        alert('No file selected!');
    } else {
        //Show Progress Bar

        numUploads.total = allFiles.length;
        $('#progressbar').progressbar({
        value : false
        });//.append("<div>37%</div>");
        $(".progress-label").html('Preparing files for upload');
        // Send each file at a time
        for (var i = 0; i < allFiles.length; i++) {
            console.log(i);
            sendFileToDrive(allFiles[i]);
        }
    }
}

function sendFileToDrive(file) {
    var reader = new FileReader();
    reader.onload = function (e) {
        var content = reader.result;
        console.log('Sending ' + file.name);
        var currFolder="Something";
        google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
    }
    reader.readAsDataURL(file);
}

function updateProgressbar( idUpdate ){
   console.log('Received: ' + idUpdate);
   numUploads.done++;
   var porc = Math.ceil((numUploads.done / numUploads.total)*100);
   $("#progressbar").progressbar({value: porc });
   $(".progress-label").text(numUploads.done +"https://foroayuda.es/"+ numUploads.total);
   if( numUploads.done == numUploads.total ){
      //uploadsFinished();
      numUploads.done = 0;
   };
}
</script>

  <script>
    function fileUploaded(status) {
      document.getElementById('myForm').style.display = 'none';
      document.getElementById('output').innerHTML = status;
    }

  </script>

  <style>
    body {
      max-width: 400px;
      padding: 20px;
      margin: auto;
    }
    input {
      display: inline-block;
      width: 100%;
      padding: 5px 0px 5px 5px;
      margin-bottom: 10px;
      -webkit-box-sizing: border-box;
      ‌​ -moz-box-sizing: border-box;
      box-sizing: border-box;
    }
    select {
      margin: 5px 0px 15px 0px;
    }
    input[type="submit"] {
      width: auto !important;
      display: block !important;
    }
    input[type="file"] {
      padding: 5px 0px 15px 0px !important;
    }
#progressbar{
    width: 100%;
    text-align: center;
    overflow: hidden;
    position: relative;
    vertical-align: middle;

}
.progress-label {
      float: left;
margin-top: 5px;
      font-weight: bold;
      text-shadow: 1px 1px 0 #fff;
          width: 100%;
    height: 100%;
    position: absolute;
    vertical-align: middle;
    }
  </style>
</body>

code.gs:

function doGet() {
  return HtmlService.createHtmlOutputFromFile('form')
    .setSandboxMode(HtmlService.SandboxMode.IFRAME);
}

function uploadFileToDrive(base64Data, fileName) {
  try{
    var splitBase = base64Data.split(','),
        type = splitBase[0].split(';')[0].replace('data:','');

    var byteCharacters = Utilities.base64Decode(splitBase[1]);
    var ss = Utilities.newBlob(byteCharacters, type);
    ss.setName(fileName);

    var dropbox = "Something"; // Folder Name
    var folder, folders = DriveApp.getFoldersByName(dropbox);

    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder(dropbox);
    }
    var file = folder.createFile(ss);

    return file.getName();
  }catch(e){
    return 'Error: ' + e.toString();
  }
}

Actualizado para mayo de 2017

Actualicé y mejoré la respuesta de Barragán.

Ventajas:

  1. Permite a los usuarios crear un nombre de subcarpeta para contener todos los archivos cargados durante esta sesión.
  2. Asegura que todas estas subcarpetas existan dentro de una carpeta específica dentro de su Google Drive
  3. La página / formulario se adapta a dispositivos móviles

Puede comenzar con este ejemplo solo para crear el script y conocer los conceptos básicos.

Entonces puedes reemplazar completamente form.html con este:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>
            Send Files
        </title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>        
        <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
        <script>

            $(document).ready(function () {

                function afterSubfolderCreated(subfolderId) {
                    console.log(subfolderId);
                    console.log(allFiles);
                    numUploads.total = allFiles.length;
                    $('#progressbar').progressbar({
                        value: false
                    });
                    $(".progress-label").html('Preparing files for upload');
                    for (var i = 0; i < allFiles.length; i++) {
                        console.log(i);
                        sendFileToDrive(allFiles[i], subfolderId);
                    }
                }

                function sendFileToDrive(file, subfolderId) {
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        var content = reader.result;
                        console.log('Sending ' + file.name);
                        google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, subfolderId);
                    }
                    reader.readAsDataURL(file);
                }

                function updateProgressbar(idUpdate) {
                    console.log('Received: ' + idUpdate);
                    numUploads.done++;
                    var porc = Math.ceil((numUploads.done / numUploads.total) * 100);
                    $("#progressbar").progressbar({value: porc});
                    $(".progress-label").text(numUploads.done + "https://foroayuda.es/" + numUploads.total);
                    if (numUploads.done == numUploads.total) {                        
                        numUploads.done = 0;
                        $(".progress-label").text($(".progress-label").text() + ': FINISHED!');
                        $("#progressbar").after('(Optional) Refresh this page if you remembered other screenshots you want to add.');//<a href="javascript:window.top.location.href=window.top.location.href"> does not work
                    }
                }

                function fileUploaded(status) {
                    document.getElementById('myForm').style.display = 'none';
                    document.getElementById('output').innerHTML = status;
                }
                var numUploads = {};
                numUploads.done = 0;
                numUploads.total = 0;
                var allFiles;
                var frm = $('#myForm');
                frm.submit(function () {
                    allFiles = document.getElementById('myFile').files;
                    if (!frm.checkValidity || frm.checkValidity()) {
                        if (allFiles.length == 0) {
                            alert('Error: Please choose at least 1 file to upload.');
                            return false;
                        } else {
                            frm.hide();
                            var subfolderName = document.getElementById('myName').value;
                            $.ajax({
                                url: '',//URL of webhook endpoint for sending a Slack notification
                                data: {
                                     title: subfolderName + ' is uploading screenshots',
                                     message: ''
                                }
                            });
                            google.script.run.withSuccessHandler(afterSubfolderCreated).createSubfolder(subfolderName);
                            return false;
                        }
                    } else {
                        alert('Invalid form');
                        return false;
                    }
                });
            });//end docReady
        </script>
        <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
        <style>
            body {
                padding: 20px;
                margin: auto;
                font-size: 20px;
            }
            label{
                font-weight: bold;
            }
            input{
                font-size: 20px;
                padding: 5px;
                display: inline-block;
                margin-bottom: 10px;
                -webkit-box-sizing: border-box;
                ‌-moz-box-sizing: border-box;
                box-sizing: border-box;
            }
            .hint{
                font-size: 90%;
                color: #666;
            }
            select {
                margin: 5px 0px 15px 0px;
            }
            input[type="file"] {
                padding: 5px 0px 15px 0px;
            }
            #progressbar{
                width: 100%;
                text-align: center;
                overflow: hidden;
                position: relative;
                vertical-align: middle;
            }
            .progress-label {
                float: left;
                margin-top: 5px;
                font-weight: bold;
                text-shadow: 1px 1px 0 #fff;
                width: 100%;
                height: 100%;
                position: absolute;
                vertical-align: middle;
            }
            li{
               padding: 10px;
            }
            @media only screen and (max-width : 520px) {
                #logo {
                    max-width: 100%;
                }
            }
        </style>
    </head>
    <body>
        <p>
            <img src="">
        </p>
        <p>This webpage allows you to send me screenshots of your dating profiles.</p>
        <ol>
            <li>
                In each of your dating apps, take a screenshot <a href="https://www.take-a-screenshot.org/" target="_blank">(how?)</a> of every part of every page of your profile.
            </li>
            <li>
                Do the same for each of your photos (at full resolution).
            </li>
            <li>
                In the form below, type your first name and last initial (without any spaces or special characters), such as SallyT.
            </li>
            <li>
                Then click the first button and select all of your screenshot images (all at once).
            </li>
            <li>
                Finally, press the last button to send them all to me!
            </li>
        </ol>
        <form> 
            <div>
                <label for="myName">Your first name and last initial:</label> 
            </div>
            <div>
                <input type="text" name="myName" placeholder="SallyT" required pattern="[a-zA-Z]+" value=""> 
                </div>
                <div>
                    <span>(No spaces or special characters allowed because this will determine your folder name)</span>
                </div>            
            <div>
                <label for="myFile">Screenshot image files:</label>

                <input type="file" name="filename" multiple>
            </div>
            <div>
                <input type="submit" value="Send File(s) ➔" >
            </div>
        </form>

        <div></div>
        <div>
            <div></div>
        </div>


    </body>
</html>

Y reemplazar completamente server.gs con este:

function doGet() {
  var output = HtmlService.createHtmlOutputFromFile('form');
  output.addMetaTag('viewport', 'width=device-width, initial-scale=1');// See http://stackoverflow.com/a/42681526/470749
  return output.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}

function uploadFileToDrive(base64Data, fileName, subfolderId) {
  Logger.log(subfolderId);
  try{
    var splitBase = base64Data.split(','),
        type = splitBase[0].split(';')[0].replace('data:','');

    var byteCharacters = Utilities.base64Decode(splitBase[1]);
    var ss = Utilities.newBlob(byteCharacters, type);
    ss.setName(fileName);
    var subfolder = DriveApp.getFolderById(subfolderId);
    var file = subfolder.createFile(ss);
    Logger.log(file);
    return file.getName() + ' at ' + file.getUrl();
  } catch(e){
    return 'createFile Error: ' + e.toString();
  }
}

function createSubfolder(subfolderName){
  var dropbox = subfolderName + Utilities.formatDate(new Date(), "US/Eastern", "_yyyy-MM-dd");
    Logger.log(dropbox);
    var parentFolderId = "{ID such as 0B9iQ20nrMNYAaHZxRjd}";
    var parentFolder = DriveApp.getFolderById(parentFolderId);
    var folder;
    try {
      folder = parentFolder.getFoldersByName(dropbox).next();      
    }
    catch(e) {
      folder = parentFolder.createFolder(dropbox);
    }
    Logger.log(folder);
  return folder.getId();
}

Unirme a la pila de respuestas anteriores, pero esto realmente me ayudó cuando implementé mi propia carga múltiple de archivos para obtener archivos en Google Drive usando la api de DriveApp V3.

Escribí y publiqué mi propia solución aquí: https://github.com/CharlesPlucker/drive-multi-upload/

Mejoras: – Maneja varios archivos de forma secuencial – Maneja archivos grandes> 50 MB – Validación

Envolví mis llamadas a la API de Google en promesas ya que tenía problemas de sincronización al crear una carpeta e inmediatamente intenté buscarla por referencia de nombre. Cada una de mis promesas solo se resolverá cuando su archivo esté completamente cargado. Para que eso funcionara, tuve que usar una fábrica de promesas. ¡Estaré encantado de explicar este código si surge la necesidad!

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *