使用Google App脚本将多个文件上传到Google云端硬盘

时间:2015-06-29 21:50:37

标签: javascript html google-apps-script

我尝试使用我的应用一次上传多个文件。它识别何时选择了2个或更多文件。但是,它只会将选定的第一个文件上传到我的驱动器。另外(虽然很小),我想知道如何将我的textarea字体改为Times New Roman以保持与其余字体一致。

Code.gs

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

function uploadFiles(form) {

  try {
    var foldertitle = form.zone + ' | Building: ' + form.building + ' | ' + form.propertyAddress + ' | ' + form.attachType;
    var folder, folders = DriveApp.getFolderById("0B7UEz7SKB72HfmNmNnlSM2NDTVVUSlloa1hZeVI0VEJuZUhSTmc4UXYwZjV1eWM5YXJPaGs");
    var createfolder = folders.createFolder(foldertitle);
    folder = createfolder;
    var blob = form.filename;
    var file = folder.createFile(blob);
    file.setDescription(" " + form.fileText);

    return "File(s) uploaded successfully! Here is the link to your file(s):     " + folder.getUrl();

  } catch (error) {
    Logger.log('err: ' + error.toString());
    return error.toString();
  }

}

function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
  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(nomeArq);

    var file = DriveApp.getFolderById("0B7UEz7SKB72HfmNmNnlSM2NDTVVUSlloa1hZeVI0VEJuZUhSTmc4UXYwZjV1eWM5YXJPaGs").createFile(ss);

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

form.html

<body>
  <div id="formcontainer">

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

    <br><br>


    <form id="myForm"> 
      <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" id="myFile" multiple>

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


    </form>
  </div>

  <div id="output"></div>

  <script>
    function iteratorFileUpload() {
        var allFiles = document.getElementById('myFile').files;

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

    // Send each file one at a time
    var i=0;
    for (i=0; i < allFiles.total; i+=1) {
      console.log('This iteration: ' + i);
      sendFileToDrive(allFiles[i]);
          };
        };
      };

    function sendFileToDrive(file) {
        var reader = new FileReader();
        reader.onload = function (e) {
        var content = reader.result;
        console.log('Sending ' + file.name);

        google.script.run
          .withSuccessHandler(fileUploaded)
          .uploadArquivoParaDrive(content, file.name, currFolder);
     }

      reader.readAsDataURL(file);
     };
  </script>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

<script>
  // Upload de arquivo dentro das pastas Arquivos Auxiliares
    function iterarArquivosUpload() {
    var arquivos = document.getElementById('inputUpload').files;

    if (arquivos.length == 0) {
        alert('No file selected!');
    } else {
        //Show Progress Bar
        numUploads.total = arquivos.length;
        $('.progressUpload').progressbar({
            value : false
        });
        $('.labelProgressUpload').html('Preparando arquivos para upload');

        // Send each file at a time
        for (var arqs = 0; arqs < numUploads.total; arqs++) {
            console.log(arqs);
            enviarArquivoParaDrive(arquivos[arqs]);
        }
    }
}

function enviarArquivoParaDrive(arquivo) {
    var reader = new FileReader();
    reader.onload = function (e) {
        var content = reader.result;
        console.log('Sending ' + arquivo.name);
        google.script.run.withSuccessHandler(updateProgressbar).uploadArquivoParaDrive(content, arquivo.name, currFolder);
    }
    reader.readAsDataURL(arquivo);
}

function updateProgressbar( idUpdate ){
   console.log('Received: ' + idUpdate);
   numUploads.done++;
   var porc = Math.ceil((numUploads.done / numUploads.total)*100);
   $('.progressUpload').progressbar({value: porc });
   $('.labelProgressUpload').html(numUploads.done +'/'+ 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;
    }
  </style>
</body>

5 个答案:

答案 0 :(得分:7)

我知道这个问题已经过时了,但在找到它和相关问题之后,我再也无法让多个文件上传了。因此,经过大量的撞击墙壁之后,我想发布一个完整的例子(.html和.gs),以防将来有人想要开始使用。当我现在部署它时,这是有效的,并且希望能够为那里的其他人工作。请注意,我刚刚将驱动器中的文件夹硬编码到code.gs文件中,但可以轻松更改。

form.html:

<body>
  <div id="formcontainer">

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

    <br><br>


    <form id="myForm"> 
      <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" id="myFile" multiple>

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


    </form>
  </div>

  <div id="output"></div>
<div id="progressbar">
    <div class="progress-label"></div>
</div>

<script src="//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 class='caption'>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 +'/'+ 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();
  }
}

答案 1 :(得分:2)

2017年5月更新

我更新并改进了barragan的答案。

优点:

  1. 允许用户创建子文件夹名称以包含在此会话期间上传的所有文件
  2. 确保这些子文件夹全部存在于Google云端硬盘中的一个指定文件夹中
  3. 页面/表单是移动设备响应
  4. 您可以从this example开始,只需创建脚本并了解基础知识。

    然后,您可以使用以下内容完全替换 form.html

    <!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="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>        
            <script src="//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 + '/' + 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="" id="logo">
            </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 id="myForm"> 
                <div>
                    <label for="myName">Your first name and last initial:</label> 
                </div>
                <div>
                    <input type="text" name="myName" id="myName" placeholder="SallyT" required pattern="[a-zA-Z]+" value=""> 
                    </div>
                    <div>
                        <span class="hint">(No spaces or special characters allowed because this will determine your folder name)</span>
                    </div>            
                <div style="margin-top: 20px;">
                    <label for="myFile">Screenshot image files:</label>
    
                    <input type="file" name="filename" id="myFile" multiple>
                </div>
                <div style="margin-top: 20px;">
                    <input type="submit" value="Send File(s) ➔" >
                </div>
            </form>
    
            <div id="output"></div>
            <div id="progressbar">
                <div class="progress-label"></div>
            </div>
    
    
        </body>
    </html>
    

    完全将 server.gs 替换为:

    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();
    }
    

答案 2 :(得分:1)

你必须一次通过script.run发送一个文件,这是我的FileReaders / ReadAsURL的实现,它使文件成为一个Base64字符串,可以很容易地传递:

注意:

  1. Dunno如果有必要,但我使用的是IFRAME沙箱
  2. 我在代码中留下了progressBar,你可以删除它
  3. 一切都必须在表格外面
  4. 它接受任何文件类型
  5. HTML:

    // Upload de arquivo dentro das pastas Arquivos Auxiliares
    function iterarArquivosUpload() {
        var arquivos = document.getElementById('inputUpload').files;
    
        if (arquivos.length == 0) {
            alert('No file selected!');
        } else {
            //Show Progress Bar
            numUploads.total = arquivos.length;
            $('.progressUpload').progressbar({
                value : false
            });
            $('.labelProgressUpload').html('Preparando arquivos para upload');
    
            // Send each file at a time
            for (var arqs = 0; arqs < numUploads.total; arqs++) {
                console.log(arqs);
                enviarArquivoParaDrive(arquivos[arqs]);
            }
        }
    }
    
    function enviarArquivoParaDrive(arquivo) {
        var reader = new FileReader();
        reader.onload = function (e) {
            var content = reader.result;
            console.log('Sending ' + arquivo.name);
            google.script.run.withSuccessHandler(updateProgressbar).uploadArquivoParaDrive(content, arquivo.name, currFolder);
        }
        reader.readAsDataURL(arquivo);
    }
    
    function updateProgressbar( idUpdate ){
       console.log('Received: ' + idUpdate);
       numUploads.done++;
       var porc = Math.ceil((numUploads.done / numUploads.total)*100);
       $('.progressUpload').progressbar({value: porc });
       $('.labelProgressUpload').html(numUploads.done +'/'+ numUploads.total);
       if( numUploads.done == numUploads.total ){
          uploadsFinished();
          numUploads.done = 0;
       };
    }
    

    Code.GS

    function uploadArquivoParaDrive(base64Data, nomeArq, idPasta) {
      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(nomeArq);
    
        var file = DriveApp.getFolderById(idPasta).createFile(ss);
    
        return file.getName();
      }catch(e){
        return 'Erro: ' + e.toString();
      }
    }
    

答案 3 :(得分:0)

@ barragan的答案在这里是我发现的最好的答案,经过数小时和数小时的搜索,许多人都在问这个问题,我已经做了一些开发来改善其他人的设计谢谢。仍然有一些错误,Chrome似乎耗尽内存并放弃任何超过100MB的文件

here's a live version

<强> server.gs

10

<强> form.html

std::vector<int> x (10); //{0,0,0,0,0,0,0,0,0,0,}
std::vector<int> x {10}; //{10} due to std::initializer_list constructor

我无法获取文本字段以发送包含详细信息的电子邮件,并且在确定如何将它们连接到Google电子表格之前已经没时间了,所以目前他们没有&#39 ; t记录添加的信息

作为一个额外的奖励,它在form.html

中看起来很棒
'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();
  }
}
'

我再次把它拿出来,因为一些被调用的脚本引起了问题。如果有人可以修复它们,它们会为表格的外观和功能添加很多东西

*编辑:我一直在玩它,只有大约一半的文件似乎到了,所以这两个代码仍有一些问题atm

答案 4 :(得分:0)

加入了许多较早的答案,但是当我实现自己的文件多上传以使用DriveApp V3 API将文件导入Google云端硬盘时,这确实对我有帮助。

我在此处撰写并发布了自己的解决方案:https://github.com/CharlesPlucker/drive-multi-upload/

改进: -顺序处理多个文件 -处理大于50MB的文件 -验证

由于我在创建文件夹并立即尝试通过名称引用获取它时遇到计时问题,因此我将Google api调用包装为promises。我的每一个诺言只会在其文件完全上传后才能解决。为了使工作正常,我不得不使用Promise Factory。如果需要,我将很高兴为您解释这段代码!

相关问题