así que básicamente la tarea es bastante simple, pero no encontré ninguna solución viable para mi problema. Tengo un gran script de carga en mi sitio web (en este momento localhost), pero reduzcamos toda la complejidad a lo único necesario.
Entonces, solo quiero cargar un solo archivo en Google Drive con Google App Script y recibir la URL para guardarlo en una var, para trabajar con esa información en un punto posterior de mi función.
Ahora el problema es que ya tengo el formulario en mi sitio web, no quiero el formulario dentro de script.google.com como html adicional, quiero transferir mi entrada de usuario a Google App Script, luego subirlo a Google Drive y devolver la URL volver a mi sitio web donde puedo guardarlo en una var.
Mi problema ahora es que no puedo poner todas las cosas juntas.
Este es el formulario en mi sitio web (simplificado):
<form name="myForm" method="post">
<!-- <form name="first-form"> -->
<input type="text" placeholder="Name" id="myName">
<input type="file" name="myFile" id="myFile">
<button onclick="UploadFile()" type="submit">submit</button>
</form>
Entonces, ¿cómo puedo cargar mi información dentro de Google Drive y obtener un resultado? ¿Cómo puedo enviar los datos en Google App Script sin usar iFrame ni nada más?
¡GRACIAS!
**** Ejemplo de trabajo si html está en scripts.google.com ****
gs
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('forms.html').setTitle("Google File Upload by CTRLQ.org");
}
function uploadFileToGoogleDrive(data, file, name, email) {
try {
var dropbox = "Received Files";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
/* Credit: www.labnol.org/awesome */
var contentType = data.substring(5,data.indexOf(';')),
bytes = Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)),
blob = Utilities.newBlob(bytes, contentType, file),
file = folder.createFolder([name, email].join(" ")).createFile(blob);
return "OK";
} catch (f) {
return f.toString();
}
}
html en aplicaciones.googlescript
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Google File Upload by CTRLQ.org</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
<style>
.disclaimer{width: 480px; color:#646464;margin:20px auto;padding:0 16px;text-align:center;font:400 12px Roboto,Helvetica,Arial,sans-serif}.disclaimer a{color:#009688}#credit{display:none}
</style>
</head>
<body>
<!-- Written by Amit Agarwal amit@labnol.org -->
<form class="main" id="form" novalidate="novalidate" style="max-width: 480px;margin: 40px auto;">
<div id="forminner">
<div class="row">
<div class="col s12">
<h5 class="center-align teal-text">Upload Files to my Google Drive</h5>
<p class="disclaimer">This <a href="http://www.labnol.org/internet/file-upload-google-forms/29170/">File Upload Form</a> (<a href="https://youtu.be/C_YBBupebvE">tutorial</a>) is powered by <a href="https://ctrlq.org/code/19747-google-forms-upload-files" target="_blank">Google Scripts</a></p>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="name" type="text" name="Name" class="validate" required="" aria-required="true">
<label for="name">Name</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input id="email" type="email" name="Email" class="validate" required="" aria-required="true">
<label for="email">Email Address</label>
</div>
</div>
<div class="row">
<div class="file-field input-field col s12">
<div class="btn">
<span>File</span>
<input id="files" type="file">
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Select a file on your computer">
</div>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<button class="waves-effect waves-light btn submit-btn" type="submit" onclick="submitForm(); return false;">Submit</button>
</div>
</div>
<div class="row">
<div class="input-field col s12" id = "progress">
</div>
</div>
</div>
<div id="success" style="display:none">
<h5 class="left-align teal-text">File Uploaded</h5>
<p>Your file has been successfully uploaded.</p>
<p>The <a href="http://www.labnol.org/internet/file-upload-google-forms/29170/">pro version</a> (see <a href="">demo form</a>) includes a visual drag-n-drop form builder, CAPTCHAs, the form responses are saved in a Google Spreadsheet and respondents can upload multiple files of any size.</p>
<p class="center-align"><a class="btn btn-large" href="https://gum.co/GA14?wanted=true" target="_blank">Upgrade to Pro</a></p>
</div>
</form>
<div class="fixed-action-btn horizontal" style="bottom: 45px; right: 24px;">
<a class="btn-floating btn-large red">
<i class="large material-icons">menu</i>
</a>
<ul>
<li><a class="btn-floating red" href="https://gum.co/GA14" target="_blank" title="Buy License - File Upload Form"><i class="material-icons">monetization_on</i></a></li>
<li><a class="btn-floating blue" href="https://youtu.be/C_YBBupebvE" target="_blank" title="Video Tutorial"><i class="material-icons">video_library</i></a></li>
<li><a class="btn-floating green" href="http://www.labnol.org/internet/file-upload-google-forms/29170/" target="_blank" title="How to Create File Upload Forms"><i class="material-icons">help</i></a></li>
</ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
<script>
var file,
reader = new FileReader();
reader.onloadend = function(e) {
if (e.target.error != null) {
showError("File " + file.name + " could not be read.");
return;
} else {
google.script.run
.withSuccessHandler(showSuccess)
.uploadFileToGoogleDrive(e.target.result, file.name, $('input#name').val(), $('input#email').val());
}
};
function showSuccess(e) {
if (e === "OK") {
$('#forminner').hide();
$('#success').show();
} else {
showError(e);
}
}
function submitForm() {
var files = $('#files')[0].files;
if (files.length === 0) {
showError("Please select a file to upload");
return;
}
file = files[0];
if (file.size > 1024 * 1024 * 5) {
showError("The file size should be < 5 MB. Please <a href="http://www.labnol.org/internet/file-upload-google-forms/29170/" target="_blank">upgrade to premium</a> for receiving larger files in Google Drive");
return;
}
showMessage("Uploading file..");
reader.readAsDataURL(file);
}
function showError(e) {
$('#progress').addClass('red-text').html(e);
}
function showMessage(e) {
$('#progress').removeClass('red-text').html(e);
}
</script>
</body>
</html>
Como se recomienda, voy a describir el proceso aquí.
Así que estamos en el sitio web: www.ejemplo.com , hay un formulario con campo de entrada de texto y campo de archivo. Digamos que ponemos una imagen y la llamamos ejemplo. Ahora, si presionamos enviar, quiero cargar la imagen en Google Drive sin ningún oAuth (es por eso que necesitamos usar el script de la aplicación de Google aquí) y nombrarlo según lo que escribimos en el campo de texto. Cuando finalice la carga, quiero que la URL de la imagen de Google Drive regrese al sitio web, para que el formulario pueda continuar trabajando con la información. Quiero guardar la url devuelta en una var luego, para luego guardarla en una base de datos. Es por eso que necesito el resultado de vuelta a mi sitio web.
Así que el esquema se parece a lo siguiente:
Ingrese la información para formar en el sitio web -> Redirigido a la secuencia de comandos de la aplicación de Google: tome la información del campo de formulario del sitio web y cargue el archivo en Google Drive y asígnele el nombre de entrada de texto -> tomar la URL de Google Drive como resultado final -> redirigir el resultado final de la URL al sitio web -> guardar el resultado de la URL en var y continuar haciendo cosas desde la función en el sitio web -> al final guardar la información de var en una base de datos -> finalizar
———————————————— EDITAR: ——————
Gracias a @Tanaike, estoy mucho más cerca del objetivo de mi desafío aquí, así que para ver dónde me quedé atascado, estoy replicando mi problema ahora:
Tomé el formulario con el script de tu ejemplo:
<form id="form">
<input name="file" id="uploadfile" type="file">
<input name="filename" id="filename" type="text">
<input id="submit" type="submit">
</form>
<script>
const form = document.getElementById('form');
form.addEventListener('submit', e => {
e.preventDefault();
const file = form.file.files[0];
const fr = new FileReader();
fr.readAsArrayBuffer(file);
fr.onload = f => {
const url = "https://script.google.com/macros/s/###/exec"; // <--- Please set the URL of Web Apps.
const qs = new URLSearchParams({filename: form.filename.value || file.name, mimeType: file.type});
fetch(`${url}?${qs}`, {method: "POST", body: JSON.stringify([...new Int8Array(f.target.result)])})
.then(res => res.json())
.then(e => console.log(e)) // <--- You can retrieve the returned value here.
.catch(err => console.log(err));
}
});
</script>
y para el script de Google:
function doPost(e) {
// const folderId = "###"; // Folder ID which is used for putting the file, if you need.
const blob = Utilities.newBlob(JSON.parse(e.postData.contents), e.parameter.mimeType, e.parameter.filename);
const file = DriveApp.getFolderById(folderId || "root").createFile(blob);
const responseObj = {filename: file.getName(), fileId: file.getId(), fileUrl: file.getUrl()};
return ContentService.createTextOutput(JSON.stringify(responseObj)).setMimeType(ContentService.MimeType.JSON);
}
Ahora, cuando intenté cargar algo, tuve el siguiente error: la política CORS no se pudo obtener. Así que cambié esta parte a la siguiente y agregué el modo no cors:
const qs = new URLSearchParams({filename: form.filename.value || file.name, mimeType: file.type});
fetch(`${url}?${qs}`, {method: "POST", mode: "no-cors", body: JSON.stringify([...new Int8Array(f.target.result)])})
Esto funcionó. Segundo intente cargar el archivo causado en el siguiente error: dice: syntax error: unexpected end of input
Así que cambié esta línea y eliminé los corchetes de res.json
JSON.stringify([...new Int8Array(f.target.result)])})
.then(res => res.json)
el tercer intento de cargar el archivo realmente funcionó con el siguiente resultado de la consola:
ƒ json() { [native code] }
Pero no hay ningún archivo cargado en Google Drive. Me estoy perdiendo algo en alguna parte. Tal vez deberíamos crear una carpeta y colocar los archivos allí.
Ah, y otra información: cuando ejecuto la función doPost en la aplicación de Google, dice:
TypeError: Cannot read property 'postData' of undefined (line 13
EDITAR2 —————————————–
yo añadí https://drive.google.com/uc?export=download&id=###ID de archivo### a su código y todo funciona bien. El archivo se está cargando.
Digamos que cargamos el archivo test.mp3 y lo llamamos testdata. Esto es lo que recibimos:
{
"filename": "testdata",
"fileId": "###some id##",
"fileUrl": "https://drive.google.com/uc?export=download&id=###fileId###"
}
Ahora, cuando abro la URL del archivo, el navegador descarga el archivo pero se llama: testdata, no testdata.mp3. Falta la terminación de tipo de archivo.
Segunda tarea: si hace clic en el enlace, quiero abrir el archivo en el navegador, cuando sea un archivo mp3, por ejemplo, quiero que pueda reproducir el sonido en la vista web, como está aquí: https://files.freemusicarchive.org/storage-freemusicarchive-org/music/Creative_Commons/Dead_Combo/CC_Affiliates_Mixtape_1/Dead_Combo_-_01_-_Povo_Que_Cas_Descalo.mp3
Espero que me puedas orientar!
Échale un vistazo: desarrolladores.google.com/picker/docs
– Cos
12 de agosto de 2020 a las 12:56
Gracias por el enlace, hasta donde yo sé, necesita la autenticación oAuth, necesito una carga pública, por lo que este enfoque no funciona para mí.
– Marcel Dz
12 de agosto de 2020 a las 12:59
Prueba una aplicación web y la marco en tu sitio web
– Cobre
12 de agosto de 2020 a las 13:04
¿Cómo se vería esto? Necesito un resultado para mi sitio web y luego guardarlo en una var, ¿es posible con un iframe?
– Marcel Dz
12 de agosto de 2020 a las 13:06
Esto es un poco difícil de seguir. ¿Puede diseñar un proceso paso a paso del flujo de trabajo?
Submit form > data gets posted to x > redirect to y
¿etc?– Espero que esto te sea útil.
12 de agosto de 2020 a las 13:07