I wrote a script for uploading files to my Google Drive using the Google Script. I deployed it as a WebApp but it's not working and I don't know why. The button just gets stuck on "Subiendo..." and never changes anything inside my Drive. I'm sure I gave the script all the permissions and I already tried to see what's happening on my own without any sucess. Can you maybe help me find what should I do? I post the code here:
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('main').setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function serverFunc(theForm) {
try{
var folder_name = "publicaciones";
var folder,folders = DriveApp.getFoldersByName(folder_name);
if(folders.hasNext()){
folder = folders.next();
}else{
folder = DriveApp.createFolder(folder_name);
}
Logger.log("TheForm", theForm == null);
var blob = theForm.theFile;
Logger.log("Blob!", blob == null);
var file = folder.createFile(blob);
Logger.log("File:", file.getName());
return "Archivo subido exitosamente: " + file.getUrl();
} catch(error){
Logger.log("error: ", error.toString());
return error.toString();
}
}
** main.html **
<div>
<form id="myForm">
<input type="file" name="theFile">
<input type="hidden" name="anExample">
<br>
<input type="button" value="Subir Archivo" onclick="this.value='Subiendo...';
google.script.run.withSuccessHandler(fileUploaded).serverFunc(this.parentNode);
return false;">
</form>
</div>
<div id="output">
</div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
I'd appreaciate any help or pointers you can give me. Thanks a lot!
Looks like there is a bug currently that Google is working on. I found a possible fix:
Change your input tag to this:
<input type="button" value="Subir Archivo" onclick="callServerCode()"/>
Add a function to the <script> tag:
<script>
function callServerCode() {
var formToSend = document.getElementById('myForm');
google.script.run
.withSuccessHandler(fileUploaded)
.serverFunc(formToSend);
};
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
Note that inside the new function, it gets the form using var formToSend = document.getElementById('myForm');
And change IFRAME to NATIVE.
It's a doc issue needs to fix with Google when using SandBoxMode=IFRAME currently. See here. I've tested it works by swapping IFRAME to NATIVE. You can simply do it:
function doGet() {
return HtmlService.createHtmlOutputFromFile('main');
}
Google has turned of NATIVE for SandBoxMode. It is now set to IFRAME only.
See here
Related
I have two input tags for uploading images and tow variables(imgFile1,imgFile2) in data section . I'm sure imgFile1 gets correct value on my console but when I upload second image, this images's value goes to wrong variable. The images d57f0.... in the picture below supposes to be in imgFile2. Why does it happen ?? Thank you so much .
html
<div class="img-field-container1">
upload img
<input type="file" class="input-img-field1" #change="uploadFile" accept="image/*" ref="img1">
</div>
<div class="img-field-container2">
upload img
<input type="file" class="input-img-field2" #change="uploadFile" accept="image/*" ref="img2">
</div>
data () {
return {
imgFile1:'',
imgFile2:'',
}
methods: {
uploadFile: function () {
var img_file1 = this.$refs.img1.files[0]
this.imgFile1 = URL.createObjectURL(img_file1)
console.log(imgFile1)→ correct value in console
var img_file2 = this.$refs.img2.files[0]
this.imgFile2 = URL.createObjectURL(img_file2)
console.log(imgFile2)→ correct value in console but updated into imgFile1
}
I solved problem by wrapping correctly
I got a component that let's the user upload a profile picture with a preview before sending it off to cloudinary.
<template>
<div>
<div
class="image-input"
:style="{ 'background-image': `url(${person.personData.imagePreview})` } "
#click="chooseImage"
>
<span
v-if="!person.personData.imagePreview"
class="placeholder"
>
<i class="el-icon-plus avatar-uploader-icon"></i>
</span>
<input
type="file"
ref="fileInput"
#change="previewImage"
>
</div>
</div>
</template>
The methods to handle the preview:
chooseImage() {
this.$refs.fileInput.click()
},
previewImage(event) {
// Reference to the DOM input element
const input = event.target;
const files = input.files
console.log("File: ", input.files)
if (input.files && input.files[0]) {
this.person.personData.image = files[0];
const reader = new FileReader();
reader.onload = (e) => {
this.person.personData.imagePreview = e.target.result;
}
// Start the reader job - read file as a data url (base64 format)
reader.readAsDataURL(input.files[0]);
}
},
This works fine, except for when the user fetches a previous project from the DB. this.person.personData.imagePreview get's set to something like https://res.cloudinary.com/resumecloud/image/upload/.....id.jpg Then when the user wants to change his profile picture, he is able to select a new one from his local file system, and this.person.personData.imagePreview is read again as a data url with base64 format. But the preview doesn't work. Only when I change routes back and forth, the correct image selected by the user is displayed.
Like I said in the comment on my post. Turns out I'm an idiot. When displaying the preview, I used this.person.personData.imagePreview . When a user fetches a project from the DB, I just did this.person.personData = response.data. That works fine, apart from the fact that I had a different name for imagePreview on my backend. So I manually set it on the same load method when fetching from the DB like: this.person.personData.imagePreview = this.loadedPersonData.file. For some reason, that screwed with the reactivity of Vue.
I want to print a web page in a pdf or extract it as a html single file.
I use data analytics tool (Apache Zeppelin) where I create a report. I want to create a static report from this tool for demo purposes. I cannot export this report from the tool (it is not embedded as an option yet) so I want to try to print in pdf. If I try to simply print it in pdf the result is a mess (images overleaping with text).
Has anyone has an idea on how to do it?
Someone suggested a solution here that you could try. Let me know if it works. Here is the code too:
%angular
<div id="divtest">Wooooo!</div>
<button id="cmd" type="submit" onclick="useJSPDF()">Generate PDF</button>
<script type="text/javascript">
function useJSPDF() {
var element = $('#divtest');
var doc = new jsPDF();
doc.fromHTML(element.html(), 15, 15,
{ 'width': 170, }
);
doc.save('sample-file.pdf');
}
if (window.jsPDF) {
} else
{ var sc = document.createElement('script'); sc.type = 'text/javascript'; sc.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/0.9.0rc1/jspdf.min.js'; sc.onerror = function(err) \{ alert(err); }
document.getElementsByTagName('head')[0].appendChild(sc);
}
</script>
Once the code is being executed, a button should be displayed like this
I'm creating a Google Web App (which is a HTML form) that will upload a file to a folder on My Drive. It's not required to have a file to upload, so there will be times where this input will essentially be "blank". The app works perfectly fine, except when you don't choose a file to upload. It spits out this error: "Exception: We're sorry, a server error occurred. Please wait a bit and try again." I have two files, the html file and the .gs file. Here's they are:
/* The script is deployed as a web app and renders the form */
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('FormFrontend.html');
}
/* This function will process the submitted form */
function uploadFiles(form) {
try {
/* Name of the Drive folder where the files should be saved */
var dropfolder = "Uploaded Files";
var folder, folders = DriveApp.getFoldersByName(dropfolder);
/* Find the folder, create the folder if it does not exist */
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropfolder);
}
/* Get the file uploaded though the form as a blob */
var blob = form.myFile;
var file = folder.createFile(blob);
var urlstr = file.getUrl()
/* Set the file description as the name of the uploader */
file.setDescription("Uploaded by " + form.ContactName);
/* Write response to spreadsheet */
var ss = SpreadsheetApp.openById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
var responses = ss.getSheetByName("Responses");
responses.appendRow([form.CompanyName, form.ContactName, form.PhoneNumber, form.Email, form.Date, form.Severity, form.Details, urlstr])
/* As long as there's no errors you should se the below text */
return "Form Submitted Successfully "
} catch (error) {
/* If there's an error, show the error message */
return error.toString();
}
}
<html>
<body>
<!-- This is the actual HTML form -->
<div id="theform">
<form id="myForm">
<p style="font-size:30px">Customer Form</p>
Company Name:
<input type="text" name="CompanyName">
<br>Contact Name:
<input type="text" name="ContactName">
<br>Phone Number:
<input type="text" name="PhoneNumber">
<br>Contact Email:
<input type="email" name="Email">
<br>Date:
<input type="date" name="Date">
<br>Overall Severity: (1 Lowest, 5 Highest)
<br>
<input type="number" name="Severity" min="1" max="5" value="1">
<br>Details:
<br>
<textarea name="Details" rows=10 cols=65></textarea>
<br>
<br>Additional File (Optional):
<input type="file" name="myFile">
<br>
<!-- The submit button. It calls the server side function uploadFiles() on click -->
<input type="submit" value="Submit" onclick="this.value='Submitting..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
</div>
<!-- Here the results of the form submission will be displayed -->
<div id="output"></div>
</body>
</html>
<!-- The function will be called after the Google Script has executed -->
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
If have tried putting an IF statement around the "/* Get the file uploaded though the form as a blob */" section that tells it to just set urlstr to nothing if form.myFile is blank, but it still fails (but if you choose an actual file, it still completes successfully). I haven't been able to get anything helpful to show up in the logger either.
I'm fairly new to Google App Script, so any help would be appreciated!
This is what ended up working. The .getContentType seems to always return "application/octet-stream" when it's left blank and checking to see if the returned content type is that specific one worked.
/* Get the file uploaded though the form as a blob */
var blob = form.myFile;
var contentType = blob.getContentType();
if (contentType != "application/octet-stream") {
var file = folder.createFile(blob);
var urlstr = file.getUrl();
/* Set the file description as the name of the uploader */
file.setDescription("Uploaded by " + form.ContactName);
} else {
var urlStr = "None given";
}
I'd check what is actually getting returned into the variable blob.
var blob = form.myFile;
Maybe check the type with JavaScript typeOf.
var whatsTheType = typeOf blob;
In this test function:
function testIt() {
var newTestFile = DriveApp.createFile('New Text File', 'Hello, world!');
var myBlob = newTestFile.getBlob();
var whatsTheType = typeof myBlob;
Logger.log('whatsTheType: ' + whatsTheType);
}
JavaScript typeof returns the type of the blob as an "object". If you check the typeof, and it's not an object, then the file wasn't uploaded.
Put in an if conditional check, rather than a "try/catch". The "try/catch" obviously isn't keeping the code from dying.
if (whatsTheType === "object") {
//Create the file
var file = folder.createFile(blob);
};
Alternatively, you should be able to check the value property of the file picker to return a name, if a file was uploaded. If there is no name for the uploaded file, then the user didn't use the file picker.
I am trying to invoke the onclick function in an html page that displays content. I am using the httpwebreqest control and not a browser control. I have traced the function and tried to find the link it calls but looking at the code below I tried inserting the link into the browser with the main url but it does not work.
<div style="position:relative;" id="column_container">
<a href="#" onclick="
if (! loading_next_page) {
loading_next_page = true;
$('loading_recs_spinner').style.visibility = 'visible';
**new Ajax.Request('/recommendations?directory=non-profit&page=**' + next_page, {
onComplete: function(transport) {
if (200 == transport.status){
$('column_container').insert({ bottom: transport.responseText });
loading_next_page = false;
$('loading_recs_spinner').style.visibility = 'hidden';
next_page += 1;
if (transport.responseText.blank()) $('show_more_recs').hide();
}
}
});
}
return false;
Any ideas would be deeply appreciated.
Thanks anyone who has viewed...but I resolved the issue. The link after the ajax request was actually correct and it just was not showing anything in the browser but the source contains all the links I need.