How to upload a image to Google Drive Shared folder and get its sharable URL? - image

currently I have a working Arduino App that takes a picture, uploads it to a Goggle Drive folder (already made public) and stores some related data on a Google Sheet including the image file name.
But I need to access this data and image from a web app running somewhere else.
The image name "filename.jpg" will not work as part of an URL.
In my current solution two scripts are used:
The first successfully transfers the image.
The second adds a line to the Google Sheet with all the necessary parameters but at this stage all I have is the filename.jpg.
I need to add something to the this second script to get filename.jpg's URL so it can be stored along with the related data on the Google Sheet.
If I could merge the functionality of both scripts in one it would do the job as the transfer script has access to the file ID but I really need help on this one.
Image transfer script:
function doPost(e) {
var myFoldername = e.parameter.myFoldername;
var myFile = e.parameter.myFile;
var myFilename = e.parameter.myFilename;
//var myFilename = Utilities.formatDate(new Date(), "GMT", "yyyyMMddHHmmss")+"-"+e.parameter.myFilename;
var myToken = e.parameter.myToken;
var contentType = myFile.substring(myFile.indexOf(":")+1, myFile.indexOf(";"));
var data = myFile.substring(myFile.indexOf(",")+1);
data = Utilities.base64Decode(data);
var blob = Utilities.newBlob(data, contentType, myFilename);
// Save a captured image to Google Drive.
var folder, folders = DriveApp.getFoldersByName(myFoldername);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(myFoldername);
}
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + myFilename);
var imageID = file.getUrl().substring(file.getUrl().indexOf("/d/")+3,file.getUrl().indexOf("view")-1);
var imageUrl = "https://drive.google.com/uc?authuser=0&id="+imageID;
// Send a link message to Line Notify.
var res = "Line Notify: ";
try {
var url = 'https://notify-api.line.me/api/notify';
var response = UrlFetchApp.fetch(url, {
'headers': {
'Authorization': 'Bearer ' + myToken,
},
'method': 'post',
'payload': {
'message': imageUrl
}
});
res += response.getContentText();
} catch(error) {
res += error;
}
return ContentService.createTextOutput(myFoldername+"/"+myFilename+"\n"+imageUrl+"\n"+res);
}
Google Sheet Script:
var timeZone = "UTC"; //get yours at https://www.timeanddate.com/time/zones/
var dateTimeFormat = "dd/MM/yyyy HH:mm";
var enableSendingEmails = true;
var emailAddress = ""; // comma separate for several emails
// 'bob#example.com';
// 'bob#example.com,admin#example.com';
function doGet(e) {
var result = 'Ok'; // default result
if (e.parameter == 'undefined') {
result = 'No Parameters';
} else {
var alarm= e.parameter.alarm;
if (typeof alarm != 'undefined') {
sendEmail("alarm text:" + stripQuotes(alarm));
return ContentService.createTextOutput(result);
}
var sheet = getSpreadSheet();
var lastRow = sheet.getLastRow();
var newRow = 1;
if (lastRow > 0) {
var lastVal = sheet.getRange(lastRow, 1).getValue();
//if there was no info for (sentEmailIfUnitIsOutForMinutes) checkIfDead() function will append row with 'dead' text
// so checking do we need to override it
if (lastVal == 'dead')
newRow = lastRow; //to overwrite "dead" value
else
newRow = lastRow + 1;
}
var rowData = [];
var namesOfParams=[];
for (var param in parseQuery(e.queryString))
namesOfParams.push(param);
// namesOfParams=namesOfParams.reverse();
//creatating headers if first row
if (newRow == 1) {
rowData[0] = "Date";
var i = 1;
for (var i=0; i<namesOfParams.length;i++ ) {
rowData[i+1] = namesOfParams[i];
}
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
rowData = [];
newRow++;
}
rowData[0] = Utilities.formatDate(new Date(), timeZone, dateTimeFormat);
for (var i=0; i<namesOfParams.length;i++ ) {
var value = stripQuotes(e.parameter[namesOfParams[i]]);
rowData[i+1] = value;
}
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
// Return result of operation
return ContentService.createTextOutput(result);
}
// Remove leading and trailing single or double quotes
function stripQuotes(value) {
return value.replace(/^["']|['"]$/g, "");
}
function parseQuery(queryString) {
var query = {};
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
}
return query;
}
function sendEmail(message) {
if (!enableSendingEmails)
return;
var subject = 'Something wrong with your esp';
MailApp.sendEmail(emailAddress, subject, message);
}
function getSpreadSheet() {
return SpreadsheetApp.getActiveSheet();
}
Assistance welcome.
Thanks
Paulo

Problem solved with the following script:
var timeZone = "GMT";
var dateTimeFormat = "dd/MM/yyyy HH:mm:ss";
var logSpreadSheetId = "1W1ypQEkfKNFSqhtfgbjbjFgzHO8LDaTv6mNWTP9h4M8";
// logSpreadSheetId is to be copied from the sheet's URL as follows: https://docs.google.com/spreadsheets/d/1W1ypQEkfKNFSqhtfgbjbjFgzHO8LDaTv6mNWTP9h4M8/edit#gid=0
function doPost(e) {
var myFoldername = e.parameter.myFoldername;
var myFile = e.parameter.myFile;
//var myFilename = e.parameter.myFilename;
//var myFilename = Utilities.formatDate(new Date(), timeZone, "ddMMyyyyHHmmss")+"-"+e.parameter.myFilename;
var myFilename = Utilities.formatDate(new Date(), timeZone, "ddMMyyyyHHmmss")+".jpg";
var myToken = e.parameter.myToken;
var contentType = myFile.substring(myFile.indexOf(":")+1, myFile.indexOf(";"));
var data = myFile.substring(myFile.indexOf(",")+1);
data = Utilities.base64Decode(data);
var blob = Utilities.newBlob(data, contentType, myFilename);
// Save a captured image to Google Drive.
var folder, folders = DriveApp.getFoldersByName(myFoldername);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(myFoldername);
}
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + myFilename);
var imageID = file.getUrl().substring(file.getUrl().indexOf("/d/")+3,file.getUrl().indexOf("view")-1);
var imageUrl = "https://drive.google.com/uc?authuser=0&id="+imageID;
addLog(myFilename,imageUrl);
return ContentService.createTextOutput(myFoldername+"/"+myFilename+"\n"+imageUrl+"\n"); //+res);
}
function addLog(myFilename,imageUrl) {
var spr = SpreadsheetApp.openById(logSpreadSheetId);
var sheet = spr.getSheets()[0];
var data = sheet.getDataRange().getValues();
var pos = sheet.getLastRow();
var rowData = [];
if(!pos>0){
pos = 1;
rowData[0] = "Date";
rowData[1] = "Image";
rowData[2] = "URL";
var newRange = sheet.getRange(pos, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
pos = pos +1;
rowData = [];
rowData[0] = Utilities.formatDate(new Date(), timeZone, dateTimeFormat);
rowData[1] = myFilename;
rowData[2] = imageUrl;
var newRange = sheet.getRange(pos, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
Also, for simplicity, the sheet and the script now sit on independent files as the script can refer to the sheet using its ID as in: var logSpreadSheetId = "1W1ypQEkfKNFSqhtfgbjbjFgzHO8LDaTv6mNWTP9h4M8"; (Please used the ID of your own sheet).

Related

How to trigger the change event of Kendo Jquery Spreadsheet when using custom Paste function?

I tried the below custom paste function to paste only values but it doesn't trigger the change event in order for me to sync the data to the data source.
Dojo Demo Link
...
change: onExcelChange,
paste: function(e) {
e.preventDefault()
var currentRange = e.range;
var fullData = e.clipboardContent.data;
var mergedCells = e.clipboardContent.mergedCells;
var topLeft = currentRange.topLeft();
var initialRow = topLeft.row;
var initialCol = topLeft.col;
var origRef = e.clipboardContent.origRef;
var numberOfRows = origRef.bottomRight.row - origRef.topLeft.row + 1;
var numberOfCols = origRef.bottomRight.col - origRef.topLeft.col + 1;
var spread = e.sender;
var sheet = spread.activeSheet();
var rangeToPaste = sheet.range(initialRow, initialCol, numberOfRows, numberOfCols);
sheet.batch(function() {
for(var i = 0; i < fullData.length; i += 1) {
var currentFullData = fullData[i];
for(var j = 0; j < currentFullData.length; j += 1 ) {
var range = sheet.range(initialRow + i, initialCol + j);
var value = currentFullData[j].value;
if (value !== null) {
range.input(value);
range.format(null);
}
}
}
sheet.select(rangeToPaste);
}, { layout: true, recalc: true });
} ...
I have tried to use recalc: true in sheet.batch to trigger the change to no avail. Any help would be greatly appreciated.
All Kendo widgets inherit from Observable, which has a trigger method:
var obj = new kendo.Observable();
obj.bind("myevent", function(e) {
console.log(e.data); // outputs "data"
});
obj.trigger("myevent", { data: "data" });
You need to manually trigger the Spreadheet's change event with its correct parameters.

Ckeditor scrollbar marker / Text Position Indicator

I would like to implement scrollbar marker into ckeditor and i can't seem to find the right way to do it i have triyed this code
var win = new CKEDITOR.dom.window( window );
var pos = win.getScrollPosition();
console.log(pos);
but it only return the google chrome scrollbar x=0 & Y=0
var win = new CKEDITOR.dom.window( domWindow );
var pos = win.getScrollPosition();
console.log(pos);
and this give me an error domWindow is not defined
i found this example it may help: https://codepen.io/Rplus/pen/mEjWJm
(() => {
var containerQS = '.article';
var container = document.querySelector(containerQS);
var form = document.querySelector('.form');
var input = form.querySelector('input[type="text"]');
var markClass = 'mark';
var markerHeight = '2px';
var _color = 'currentColor';
var containerY = container.offsetTop;
var containerH = container.scrollHeight;
var customStyle = document.createElement('style');
container.appendChild(customStyle);
var renderScrollMarker = ($parent, posArr) => {
var _posArr = posArr.map(i => {
return `transparent ${i}, ${_color} ${i}, ${_color} calc(${i} +
${markerHeight}), transparent calc(${i} + ${markerHeight})`;
});
customStyle.innerHTML = `article::-webkit-scrollbar-track {
background-image: linear-gradient(${_posArr.join()});
}`;
};
var calcEleRelativePos = ($ele) => {
return ($ele.offsetTop - containerY) / containerH;
};
var markOpt = {
className: markClass,
done: function () {
var marks = document.querySelectorAll(`.${markClass}`);
var allY = [].map.call(marks, (mark) => {
return (calcEleRelativePos(mark) * 100).toFixed(2) + '%';
});
renderScrollMarker(container, allY);
console.log(allY);
}
};
var instance = new Mark(container);
form.addEventListener('submit', (e) => {
e.preventDefault();
var _text = input.value.trim();
console.log(_text, form.oldText);
if (_text === '') {
instance.unmark(markOpt);
return;
}
form.oldText = _text;
instance.unmark().mark(_text, markOpt);
});
// trigger
form.querySelector('input[type="submit"]').click();
})();
but as ckeditor secures a lot of element, i would love to know if any one has done this before with CKeditor
i just got the real editor scrollbar position, i only need to put a marker using style or any availble methode
var win=CKEDITOR.instances.editor1.document.getWindow();
var pos = win.getScrollPosition().y;
console.log(pos);
this worked for me :
var jqDocument = $(editor.document.$);
var documentHeight = jqDocument.height();
var scrollTo =jqDocument.scrollTop();
var docHeight = jqDocument.height();
var scrollPercent = (scroll)/(docHeight);
var scrollPercentRounded = Math.round(scrollPercent*100);
$(".ui-slider-handle").css("bottom", 100-scrollPercentRounded+"%");

httpRequest inside for loop sets same value for all records

I want to build and return an array of objects from CloudCode based on a query and the result of a httpRequest done for each record.
The problem with the following (example) is that it adds the same value for all "element" objects for all records. From testing I know that the variables "outside" the promises.push(Parse.Cloud.httpRequest(.. (e.g. "countryName") are unique.
What am I missing here?
Thanks!
Parse.Cloud.define("search3", function(request, response) {
var rs = [];
var promises = [];
// Query CountryTemp class
var query = new Parse.Query('CountryTemp');
query.limit(1000);
query.exists("Country");
query.include("Country");
query.greaterThan('Month11', 25);
query.find().then(function(results) {
for (var i = 0; i < results.length; ++i) {
var element = {};
var result = results[i];
var country = result.get("Country");
var countryID = country.id;
var countryName = country.get("Name");
var temp = result.get("Month11");
promises.push(Parse.Cloud.httpRequest({
url: 'http://www.google.com'
}).then(function(httpResponse){
element.id = countryID;
element.countryName = countryName;
element.temp = result.get("Month11");
element.httpresponse = httpResponse.text.substr(0, 50);
rs.push(element);
}));
}
return Parse.Promise.when(promises);
}).then(function() {
response.success(rs);
}, function() {
response.error('error');
});
});
Found the problem, Using underscore "_each" instead of "for" fixed it:
var _ = require('underscore');
..
_.each(results, function(result) {

Resize image and upload in couchdb or upload url blob to couchdb

I need to upload attached resized images into a couchdb doc. Right now I'm not resizing images, only uploading them by using the following code:
function attachFile(event) {
event.preventDefault();
var form_data = {};
$("form.attach-file :file").each(function() {
form_data[this.name] = this.value;
});
if (!form_data._attachments || form_data._attachments.length == 0) {
alert("Please select a file to upload.");
return;
}
var id = $("#ant-show").data("doc")._id;
$(this).ajaxSubmit({
url: "db/" + $.couch.encodeDocId(id),
success: function(resp) {
$('#modal-attach').modal("hide");
helios_link(id);
}
});
}
The code I'm using to rezise images, but that doesn't work to upload them, is the following:
function attachFile(event) {
function isImage (str) {
return str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
}
function resizeAndUpload(file, callback, progress)
{
var reader = new FileReader();
reader.onloadend = function() {
var tempImg = new Image();
tempImg.onload = function() {
var MAX_WIDTH = 500;
var MAX_HEIGHT = 500;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var resizedCanvas = document.createElement('canvas');
resizedCanvas.width = tempW;
resizedCanvas.height = tempH;
var ctx = resizedCanvas.getContext("2d");
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataURL = resizedCanvas.toDataURL("image/jpeg");
var file = dataURLtoBlob(dataURL);
var fd = $("#upload");
fd.append("_attachments", file);
var id = $("#ant-show").data("doc")._id;
console.log(fd);
fd.ajaxSubmit({
url: "db/" + $.couch.encodeDocId(id),
success: function(resp) {
$('#modal-attach').modal("hide");
helios_link(id);
}
});
};
tempImg.src = reader.result;
}
reader.readAsDataURL(file);
}
function dataURLtoBlob(dataURL) {
// Decodifica dataURL
var binary = atob(dataURL.split(',')[1]);
// Se transfiere a un array de 8-bit unsigned
var array = [];
var length = binary.length;
for(var i = 0; i < length; i++) {
array.push(binary.charCodeAt(i));
}
// Retorna el objeto Blob
return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}
function uploaded(response) {
// Código siguiente a la subida
}
function progressBar(percent) {
// Código durante la subida
}
event.preventDefault();
console.clear();
var files = document.getElementById('_attachments').files;
console.log(files);
resizeAndUpload(files[0], uploaded, progressBar);
}
Do anybody know how can I improve my code to make it work? I would like to have in fact two different solutions, one that helps me to improve my code and the second one, to get instructions on how to upload a URL BLOB as attachments into a couchdb document.

retrieve data from c# linq object to json to html

Retrieve code from json.
C#code:-
var collection = getsortcat.Select(x => new
{
idterm = x.IDTerm,
mvo = x.MVO,
pic = x.Pic,
said = x.SAid,
termactive = x.TermActive,
vid = x.Vid,
fvo = x.FVO,
eterm = x.ETerm,
edef = x.EDef,
buse = x.BUse,
bterm = x.BTerm,
idcat = x.TermCat,
items = x.TermCategory1.IDCat,
catname = x.TermCategory1.TermCategory1
});
JavaScriptSerializer jss = new JavaScriptSerializer();
string output = jss.Serialize(collection);
return Json(output, JsonRequestBehavior.AllowGet);
Javascript Code:-
success: function (e) {
var txt = "'{ data :" + e + "}'";
var obj = eval("(" + txt + ")");
$('#pdata').append(obj.data[0]);
},
Not getting output. Please give me solution how to retrieve data from c# linq object to json to html?
First fix your controller action to get rid of any JavaScriptSerializers and manual plumbing code. Directly return the collection to the Json result:
var collection = getsortcat.Select(x => new
{
idterm = x.IDTerm,
mvo = x.MVO,
pic = x.Pic,
said = x.SAid,
termactive = x.TermActive,
vid = x.Vid,
fvo = x.FVO,
eterm = x.ETerm,
edef = x.EDef,
buse = x.BUse,
bterm = x.BTerm,
idcat = x.TermCat,
items = x.TermCategory1.IDCat,
catname = x.TermCategory1.TermCategory1
});
return Json(collection, JsonRequestBehavior.AllowGet);
Now inside the success callback the e parameter already represents an array of objects that were parsed. You don't need to call any eval. Directly access the elements (by index) and then the properties:
success: function (e) {
var txt = e[0].mvo;
},
you could also loop through the elements:
success: function (e) {
for (var i = 0; i < e.length; i++) {
var element = e[i];
alert(element.idterm);
}
},

Resources