【问题标题】:Upload an image to a Google spreadsheet from WEB FORM从 WEB FORM 将图像上传到 Google 电子表格
【发布时间】:2021-01-23 15:47:36
【问题描述】:

所以基本上 它从谷歌表格自动生成的脚本。我找不到可以帮助我调整它的链接或任何东西,以便我可以从我的网站上传图片。它只发送图像名称而不是实际图像。 如果有人能解释我如何调整它以便发送实际图像,我将非常高兴。

<input type="text" id="email" name="email:" placeholder="">
 <input type="file" id="myFile" name="filename">
                    
 <button>
   Send
</button>
Out put
Email: Someone@gmail.com
FileName: Untitled-1.jpg

// if you want to store your email server-side (hidden), uncomment the next line
 var TO_ADDRESS = "***@gmail.com";

// spit out all the keys/values from the form in HTML for email
// uses an array of keys if provided or the object to determine field order
function formatMailBody(obj, order) {
  var result = "";
  if (!order) {
    order = Object.keys(obj);
  }
  
 
  
  // loop over all keys in the ordered form data
  for (var idx in order) {
    var key = order[idx];
    result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + sanitizeInput(obj[key]) + "</div>";
    // for every key, concatenate an `<h4 />`/`<div />` pairing of the key name and its value, 
    // and append it to the `result` string created at the start.
  }
  return result; // once the looping is done, `result` will be one long string to put in the email body
}

// sanitize content from the user - trust no one 
// ref: https://developers.google.com/apps-script/reference/html/html-output#appendUntrusted(String)
function sanitizeInput(rawInput) {
   var placeholder = HtmlService.createHtmlOutput(" ");
   placeholder.appendUntrusted(rawInput);
  
   return placeholder.getContent();
 }

function doPost(e) {

  try {
    Logger.log(e); // the Google Script version of console.log see: Class Logger
    record_data(e);
    
    // shorter name for form data
    var mailData = e.parameters;

    // names and order of form elements (if set)
    var orderParameter = e.parameters.formDataNameOrder;
    var dataOrder;
    if (orderParameter) {
      dataOrder = JSON.parse(orderParameter);
    }
    
    // determine recepient of the email
    // if you have your email uncommented above, it uses that `TO_ADDRESS`
    // otherwise, it defaults to the email provided by the form's data attribute
    var sendEmailTo = (typeof TO_ADDRESS !== "undefined") ? TO_ADDRESS : mailData.formGoogleSendEmail;
    
    // send email if to address is set
    if (sendEmailTo) {
      MailApp.sendEmail({
        to: String(sendEmailTo),
        subject: "Contact form submitted",
        // replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
        htmlBody: formatMailBody(mailData, dataOrder)
      });
    }

    return ContentService    // return json success results
          .createTextOutput(
            JSON.stringify({"result":"success",
                            "data": JSON.stringify(e.parameters) }))
          .setMimeType(ContentService.MimeType.JSON);
  } catch(error) { // if error return this
    Logger.log(error);
    return ContentService
          .createTextOutput(JSON.stringify({"result":"error", "error": error}))
          .setMimeType(ContentService.MimeType.JSON);
  }
}


/**
 * record_data inserts the data received from the html form submission
 * e is the data received from the POST
 */
function record_data(e) {
  var lock = LockService.getDocumentLock();
  lock.waitLock(30000); // hold off up to 30 sec to avoid concurrent writing
  
  try {
    Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
    
    // select the 'responses' sheet by default
    var doc = SpreadsheetApp.getActiveSpreadsheet();
    var sheetName = e.parameters.formGoogleSheetName || "responses";
    var sheet = doc.getSheetByName(sheetName);
    
    var oldHeader = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
    var newHeader = oldHeader.slice();
    var fieldsFromForm = getDataColumns(e.parameters);
    var row = [new Date()]; // first element in the row should always be a timestamp
    
    // loop through the header columns
    for (var i = 1; i < oldHeader.length; i++) { // start at 1 to avoid Timestamp column
      var field = oldHeader[i];
      var output = getFieldFromData(field, e.parameters);
      row.push(output);
      
      // mark as stored by removing from form fields
      var formIndex = fieldsFromForm.indexOf(field);
      if (formIndex > -1) {
        fieldsFromForm.splice(formIndex, 1);
      }
    }
    
    // set any new fields in our form
    for (var i = 0; i < fieldsFromForm.length; i++) {
      var field = fieldsFromForm[i];
      var output = getFieldFromData(field, e.parameters);
      row.push(output);
      newHeader.push(field);
    }
    
    // more efficient to set values as [][] array than individually
    var nextRow = sheet.getLastRow() + 1; // get next row
    sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);

    // update header row with any new data
    if (newHeader.length > oldHeader.length) {
      sheet.getRange(1, 1, 1, newHeader.length).setValues([newHeader]);
    }
  }
  catch(error) {
    Logger.log(error);
  }
  finally {
    lock.releaseLock();
    return;
  }

}

function getDataColumns(data) {
  return Object.keys(data).filter(function(column) {
    return !(column === 'formDataNameOrder' || column === 'formGoogleSheetName' || column === 'formGoogleSendEmail' || column === 'honeypot');
  });
}

function getFieldFromData(field, data) {
  var values = data[field] || '';
  var output = values.join ? values.join(', ') : values;
  return output;
}```


【问题讨论】:

  • 那么,您想在电子表格中插入图像吗?图片来自哪里?你是如何提供的?你在你的代码哪里做的?请尝试提供一个最小化的示例,我怀疑您提供的所有代码都是相关的。
  • 是的,它来自我的网站,当用户插入它发送到谷歌电子表格的图像时。
  • 因此,如果我理解正确,您希望在提交 HTML 表单(包含将选择图像的file 输入)时将图像插入电子表格。对吗?
  • 没错

标签: html forms image google-apps-script upload


【解决方案1】:

在 Apps Script web 应用程序中,为了将文件输入数据从 HTML 表单发送到服务器,推荐的方法是通过 google.script.run 调用服务器端函数。在这种情况下,您不会依赖于 doPost 函数(在对 Web 应用 URL 发出 POST 请求时调用),而是依赖于通过 @987654332 调用的服务器端函数(在下面的示例中名为 processForm) @。

以这种方式调用服务器端函数时,如果将 HTML 表单元素作为参数传递,则可以访问输入字段名称,如 here 解释:

如果您以表单元素作为参数调用服务器函数,则表单将成为单个对象,其中字段名称作为键,字段值作为值。除了文件输入字段的内容变成Blob对象之外,这些值都被转换为字符串。

现在,在决定如何将图像插入电子表格时,您有多种选择,具体取决于:

  • 是要将图像插入特定单元格还是将图像插入单元格上(未绑定到特定单元格)。
  • 图片的大小。
  • 您是否担心公开访问此图片。

方法#1。使用 insertImage:

如果您想在“单元格上方”插入图片(即图片不在一个特定的单元格中),并且如果您不希望此图片可公开访问,您只需提供图片对应的blob作为Sheet.insertImage(blobSource, column, row)的参数。

对应的代码可能是这样的:

index.html:

<html>
  <body>
    <form>
      <input type="text" id="email" name="email:" placeholder="">
      <input type="file" id="myFile" name="filename">      
      <input type="button" value="Send" onclick="google.script.run.processForm(this.parentNode)">
    </form>
  </body>
</html>

代码.gs:

function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}

function processForm(e) {
  var contentType = 'image/jpeg'; // Could also be 'image/bmp', 'image/gif', or 'image/png'
  var image = e.filename;
  var image = image.getAs(contentType);
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Sheet1"); // Change sheet name if necessary
  sheet.insertImage(image, 1, 1); // Top-left corner of image is top-left corner of A1 (image not in A1, but "over cells")
}

可以使用输入namee 检索来自输入字段的其他数据。例如,输入的email 将通过e["email:"] 检索。

重要提示:由于this issue,超过一定尺寸的图片无法通过insertImage插入工作表;尝试这样做会导致以下错误消息 Exception: Service error: Spreadsheets(我注意到这适用于 150 KB 左右的图像,但不适用于 260 KB 左右的图像)。因此,如果您想插入更大尺寸的图像,您可能需要检查方法#2(或在插入之前调整图像大小,例如,使用this answer by Tanaike 中的解决方法)。

方法#2。使用 =IMAGE(url):

如果您想将图像插入特定单元格,并且您不关心此图像是否可公开访问,您可以通过创建指向该图像的可公开访问链接并使用函数IMAGE 来插入图像。

例如,您可以将此图片上传到云端硬盘,使其可公开访问(与Anyone with the link 共享),并通过=IMAGE(url) 添加公共网址。在这种情况下,您的服务器端函数可能是这样的(有关 URL 的更多详细信息,请参阅this):

function processForm(e) {
  var contentType = 'image/jpeg';
  var image = e.filename;
  var image = image.getAs(contentType);
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Sheet1"); // Change sheet name if necessary
  var file = DriveApp.createFile(image); // Add image to Drive
  file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW); // Share image with Anyone
  sheet.getRange("A1").setFormula("=IMAGE(\"https://drive.google.com/uc?export=view&id=" + file.getId() + "\")");
}

这种方法的一个优点是您可以插入更大尺寸的图像。

重要提示:

  • 目前,由于this issue,如果启用了V8,则无法通过HTML表单文件输入字段成功上传图像。因此,您必须禁用 V8 运行时才能使其工作(点击Run &gt; Disable new Apps Script runtime powered by Chrome V8)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多