I am creating an application using asp.net mvc and javascript in which I want to create folders inside my existing google drive folder.
below is my code which I got from stackoverflow
function createFolder() {
var body = {
'title': document.getElementById('txtFolderName').value,
'mimeType': "application/vnd.google-apps.folder"
};
var request = gapi.client.drive.files.insert({
'resource': body
});
request.execute(function (resp) {
console.log('Folder ID: ' + resp.id);
});
}
I am getting the below error
index.html:61 Uncaught TypeError: Cannot read properties of undefined
(reading 'files')
on the following line
var request = gapi.client.drive.files.insert({
here gapi.client.drive is appearing to be undefined
below is my code to authenticate and load google api client
function authenticate(callback) {
return gapi.auth2.getAuthInstance()
.signIn({ scope: "https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file" })
.then(function () {
console.log("Sign-in successful");
callback == undefined ? '' : callback();
},
function (err) {
console.error("Error signing in", err);
});
}
function loadClient() {
gapi.client.setApiKey("APIKEY");
return gapi.client.load("https://docs.googleapis.com/$discovery/rest?version=v1")
.then(function () {
console.log("GAPI client loaded for API");
},
function (err) {
console.error("Error loading GAPI client for API", err);
});
}
what is the problem here?
and what I need to do if I want to create a folder inside another folder?
thanks in advance
I thought that in your script, https://docs.googleapis.com/$discovery/rest?version=v1 of gapi.client.load("https://docs.googleapis.com/$discovery/rest?version=v1") is used for Google Docs API v1. I think that the reason for your error message of Uncaught TypeError: Cannot read properties of undefined (reading 'files') is due to this.
In your goal, it seems that you want to create a folder into a specific folder. In this case, please use Drive API. But, when I saw your current script for creating the folder, Drive API v2 is used. So, please modify as follows.
From:
return gapi.client.load("https://docs.googleapis.com/$discovery/rest?version=v1")
To:
return gapi.client.load("https://www.googleapis.com/discovery/v1/apis/drive/v2/rest")
By this modification, I thought that your createFolder() works. But in your current createFolder(), the folder is created to the root folder. When you want to create the folder into a specific folder, please modify the request body as follows.
var body = {
'title': document.getElementById('txtFolderName').value,
'mimeType': "application/vnd.google-apps.folder",
'parents': [{'id': '###folderId###'}]
};
Note:
As additional information, if you want to use Drive API v3, please modify it as follows.
From
return gapi.client.load("https://docs.googleapis.com/$discovery/rest?version=v1")
To
return gapi.client.load("https://www.googleapis.com/discovery/v1/apis/drive/v3/rest")
And, please modify createFolder() as follows.
var body = {
'name': document.getElementById('txtFolderName').value,
'mimeType': "application/vnd.google-apps.folder",
'parents': ['###folderId###']
};
var request = gapi.client.drive.files.create({ 'resource': body });
References:
Files: insert of Drive API v2
Files: create of Drive API v3
Related
I'm trying to use Keycloak with JavaScript and these are the steps that I followed.
I create a client inside KeyCloak admin panel.
Link to image
I copy the .json file to my apache folder.
{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "test",
"public-client": true,
"confidential-port": 0
}
I go to my index.html and I add these two lines for calling the script.
<script src="keycloak.js"></script>
<script>
function initKeycloak() {
const keycloak = new Keycloak();
keycloak.init().then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
}
</script>
this is what i have in myLogical.js
var keycloak = new Keycloak();
function initKeycloak() {
keycloak.init({onLoad: 'login-required'}).then(function() {
constructTableRows(keycloak.idTokenParsed);
pasteToken(keycloak.token);
}).catch(function() {
alert('failed to initialize');
});
}
function constructTableRows(keycloakToken) {
document.getElementById('row-username').innerHTML = keycloakToken.preferred_username;
document.getElementById('row-firstName').innerHTML = keycloakToken.given_name;
document.getElementById('row-lastName').innerHTML = keycloakToken.family_name;
document.getElementById('row-name').innerHTML = keycloakToken.name;
document.getElementById('row-email').innerHTML = keycloakToken.email;
}
function pasteToken(token){
document.getElementById('ta-token').value = token;
document.getElementById('ta-refreshToken').value = keycloak.refreshToken;
}
var refreshToken = function() {
keycloak.updateToken(-1)
I tried to download the file keycloak.js and put it directly on my root folder but it happen the same problem.
These is the message I got when I try to open the page
I'm confused about point 1, does keycloak automatically load configuration from json file in Apache folder? Let's assume that no, and I think that where your problem lies, you're not passing config param to keycloak constructor.
How to initialize keycloak:
const initKeycloak = async () => {
//you can hardcode these values for now just to see if everything works
const config = { url: 'http://localhost:8080/auth', realm: 'master', clientId: 'test'};
const keycloak = new Keycloak(config);
await keycloak
.init({ onLoad: 'login-required' })
.then(isAuthenticated => {
//user is authenticated
})
.catch(error => { console.log('keycloak error', error); });
}
Another important thing is that keycloak-js library version (in package.json) must match keycloak server version. Sometimes different versions work with each other but it's always best practice that keycloak-js version matches keycloak server version.
You can also look here: https://github.com/m-s7/react-core/blob/devel/src/services/keycloak-service.ts this is my repo with working keycloak-js implementation.
I'm using googleapis to upload different files to the Google Drive. The scenario is:
User provides a document and it's information through my REST API (I'm using NodeJS).
The REST API creates the directory that will contain the document, if it's not already exist.
The REST API uploads the document to that directory.
The structure of the drive is:
/root/documents/$type/$new_document
where $type is one of the user's provided fields and the $new_document is the document that was provided by the user.
The way I connect:
oauth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
drive_instance = google.drive({
version: 'v3',
auth: oauth2Client,
});
I figured how to upload the document to root folder of the Google Drive:
}
try {
const response = await drive.files.create({
requestBody: {
name: file.name,
mimeType: file.mimetype,
},
media: {
mimeType: file.mimetype,
body: file.data,
},
});
console.log(response.data);
} catch (error) {
console.log(error.message);
}
What I'm struggling is:
How to create the directory /root/documents/$type if it's not already existing?
How to upload the $new_document to /root/documents/$type?
For the second question, I know that the docs provide an option of parents[] that will contain all the folder IDs. but then, how can I get the folder ID of /root/documents/$type? Is there someway to combine the steps (like maybe mkdir -p for the directories or creating the directory will return the ID of the directory).
1. Try found folder you need via drive.files.list() method
You need set filter. Example:
add 'q': "..." in requestBody to search what you need
use "name = 'Some Folder Name'" to search by name
use "mimeType = 'application/vnd.google-apps.folder'" to search only folders
Thus, combine via and:
'q': "name = 'Some Folder Name' and mimeType = 'application/vnd.google-apps.folder'" to find all folders with name you chose
const folderName = 'Some Folder Name'
gapi.client.drive.files
.list({
'q': "name = 'Some Folder Name' and mimeType = 'application/vnd.google-apps.folder'",
'pageSize': 1000,
'fields': "files(id, name, parents)"
})
.then((response) => {
const files = response.result.files;
if (files.length > 0) {
handleSearchResult(files)
} else {
createFolder()
}
console.log(total / (1024*1024*1024))
});
About handleSearchResult() or createFolder:
It maybe more than 1 file. So you can find necessary root getting files[i].parents . That's why I added parents in 'fields': "files(id, name, parents)". https://developers.google.com/drive/api/v3/reference/files
Also you can add searching rule e.g. 'parents contain "..."''
https://developers.google.com/drive/api/v3/search-files
If search brings 0 files result so just create folder by yourself. You can create path\directory step-by step. Create first folder in drive root and remember id. After that create second folder and add in requestBody parentId that equal first folder id. And etc... Btw you can use almost the same logic to search.
2. Create folder if its necessary
Example:
// name = 'Folder Name',
// parents = ['some-parent1-id', 'some-parent2-id', ...]
function createFolder(name, parents) {
const fileMetadata = {
'name' : name,
'mimeType' : 'application/vnd.google-apps.folder',
'parents': parents
};
gapi.client.drive.files
.create({
resource: fileMetadata,
}).then((response) => {
switch(response.status){
case 200:
const file = response.result;
console.log('Created Folder Id: ' + file.id);
break;
default:
console.log('Error creating the folder, '+response);
break;
}
});
}
3. Upload file with setted parents
you should add parents = ['id-of-folder'] in requestBody
Read more in Google Drive API - Files: create
I hope it will help at least a bit:) Keep it up!
You can upload a folder inside a folder using the follow method
You should have the id of the folder you want to store the new folder in (can be extracted using nodejs api or by opening the folder and looking at the characters after last / in the url)
Use a special mimetype reserved for folders in google drive ( application/vnd.google-apps.folder )
considering your example
drive.files.create({
requestBody:{
name:"SomeFolder",
mimeType:"application/vnd.google-apps.folder"
},(error,folder)=>{
console.log(folder.data.id);
drive.files.create:({
requestBody:{
name:"SomeFolderInsideAFolder",
mimeType:"application/vnd.google-apps.folder"
},
parents:[folder.data.id]
})
})
})
You can even easily create a recursively uploading folder function by combining file upload and folder upload which can upload a whole folder
I'm having a problem with the google drive API.
I'm trying to upload an excel file with this API, but it's not working. Even copying the google API documentation doesn't work.
Here is a sample of my code:
#Get('teste')
async teste(){
const keys = require(path.resolve('src', 'files', 'api', 'keys'))
const client = new google.auth.JWT(
keys.client_email,
null,
keys.private_key,
['https://www.googleapis.com/auth/drive.metadata.readonly']
)
client.authorize((err, tokens) =>{
if(err){
console.log(err)
return;
} else{
this.gdrun(client)
}
})
}
gdrun(client){
const drive = google.drive({version: 'v3', auth: client});
var fileMetadata = {
name: 'My Report',
mimeType: 'application/vnd.google-apps.spreadsheet'
};
var media = {
mimeType: 'application/vnd.ms-excel',
body: require(path.resolve('src', 'files', 'excel', 'solargroup.xlsx'))
};
drive.files.create({
resource: fileMetadata,
media: media,
fields: 'id'
}, function (err, file: any) {
if (err) {
// Handle error
console.error(err);
} else {
console.log('File Id:', file.id);
}
});
}
I received this error:
I believe your goal as follows.
You want to upload a file (XLSX file) to Google Drive of the service account.
You want to achieve this using the service account with googleapis for Node.js.
From your script, I thought that you might wanted to upload a XLSX file as Google Spreadsheet by converting.
Modification points:
When you want to upload a file to Google Drive, in this case, please use the scope of https://www.googleapis.com/auth/drive instead of https://www.googleapis.com/auth/drive.metadata.readonly.
When you want to upload XLSX file as the XLSX file, the mimeType is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
When you want to upload a file, body: require(path.resolve('src', 'files', 'excel', 'solargroup.xlsx')) cannot be used. In this case, please use body: fs.createReadStream(path.resolve('src', 'files', 'excel', 'solargroup.xlsx')). I thought that your error message might be due to this.
When you want to retrieve the file ID of the uploaded file, please modify file.id to file.data.id.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
const client = new google.auth.JWT(
keys.client_email,
null,
keys.private_key,
['https://www.googleapis.com/auth/drive.metadata.readonly']
)
To:
const client = new google.auth.JWT(
keys.client_email,
null,
keys.private_key,
['https://www.googleapis.com/auth/drive'] // Modified
)
And also, please modify your gdrun() as follows.
gdrun(client){
const drive = google.drive({ version: "v3", auth: client });
var fileMetadata = {
name: "My Report",
mimeType: "application/vnd.google-apps.spreadsheet",
};
var media = {
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // Modified
body: fs.createReadStream(path.resolve('src', 'files', 'excel', 'solargroup.xlsx')), // Modified
};
drive.files.create(
{
resource: fileMetadata,
media: media,
fields: "id",
},
function (err, file) {
if (err) {
console.error(err);
} else {
console.log("File Id:", file.data.id); // Modified
}
}
);
}
In this case, please use const fs = require("fs").
Result:
When above script is run, the following result is obtained.
File Id: ###fileId###
Note:
Your script uploads a XLSX file to Google Drive of service account as Google Spreadsheet. In this case, you cannot directly seen the uploaded file at your Google Drive. Because the Google Drive of the service account is different from your Google Drive. When you want to see the uploaded file at your Google Drive, please create a folder on your Google Drive and share the created folder with the email of the service account. And then, please upload the file to the shared folder. By this, you can see the uploaded file on your Google Drive with your browser. For this, please modify fileMetadata as follows.
var fileMetadata = {
name: "My Report",
mimeType: "application/vnd.google-apps.spreadsheet",
parents: ["### folderId ###"], // Please set the folder ID of the folder shared with the service account.
};
In above script, the maximum file size is 5 MB. Please be careful this. When you want to upload a file more than 5 MB, please use resumable upload. Ref
References:
Upload file data
Files: create
I hope there is few among you who have experience with Jaspersoft Reports and their new visualise.js api
I have a problem with visualise.js not producing report export file. What happens is:
I am able to succsefully load the report through the visualise.js API, it loads and displays on my web page
Export controls load up successfully too, so I have dropdown with export file formats and a button to export the file.
When I click the export button though, the whole page reloads as if the export button was really a submit button and nothing happens.
Occasionally, the export will work and it will produce file. Though there is no pattern to when it will produce the file and when it will fail.
Below is the code I am using for this (I am using plain text auth for testing purposes):
visualize({
auth: {
name: "mylogin",
password: "mypass",
organization: "organization_1"
}
}, function (v) {
var $select = buildControl("Export to: ", v.report.exportFormats),
$button = $("#button"),
report = v.report({
resource: "/FPSReports/journal",
container: "#export",
params: {
"journal_ref": [ "<?php echo $reference; ?>" ],
},
success: function () {
button.removeAttribute("disabled");
},
error : function (error) {
console.log(error);
}
});
$button.click(function () {
console.log($select.val());
report.export({
// export options here
outputFormat: $select.val(),
// exports all pages if not specified
// pages: "1-2"
}, function (link) {
var url = link.href ? link.href : link;
window.location.href = url;
}, function (error) {
console.log(error);
});
});
function buildControl(name, options){
function buildOptions(options) {
var template = "<option>{value}</option>";
return options.reduce(function (memo, option) {
return memo + template.replace("{value}", option);
}, "")
}
var template = "<label>{label}</label><select>{options}</select><br />",
content = template.replace("{label}", name)
.replace("{options}", buildOptions(options));
var $control = $(content);
$control.insertBefore($("#button"));
//return select
return $($control[1]);
}
});
HTML:
<div class="grid">
<div class="grid-8"></div>
<div class="grid-8 center">Export</div>
<div class="grid-8"></div>
</div>
<div class="grid">
<div class="grid-24" id="export"></div>
</div>
The only parameter comes from URI segment (I am using codeigniter framework):
$reference = $this->uri->segment(3, 0);
I have found an answer that seems to work, and has resolved the issue. Posting it here in case anyone else has this specific problem like I did.
In brief:
After spending hours looking at console debug output I have realised that each time I tried to send a request for export a new session would be opened. Without logging out of the previous one. And apparently that is a no-no. I do not know JS very well but from what I understood there was session id mismatch in request. Please feel free to correct me here :)
The solution to this problem (or for example if you are having authentication issues with visualize.js) is very simple. Set the authentication in global config:
visualize.config({
auth: {
name: "superuser",
password: "superuser"
}
});
No matter if you are using tokens or plain text or whatever else auth is available through the api.
Then do your stuff wherever else on your website:
visualize(function (v) {
v("#container1").report({
resource: "/public/Samples/Reports/06g.ProfitDetailReport",
error: function (err) {
alert(err.message);
}
});
});
visualize(function (v) {
v("#container2").report({
resource: "/public/Samples/Reports/State_Performance",
error: function (err) {
alert(err.message);
}
});
});
Everything should work for you as it did for me. This works in version 5.6 and 6.1 of visualize.js.
Further reading and links from my research:
Token based authentication to Jasper reports failing when used with visualize.js
Visualize.js authentication error after second login
http://community.jaspersoft.com/questions/842695/visualizejs-authentication-error
http://community.jaspersoft.com/questions/845886/authentication-error-refresh-credentials-visualizejs
Code example (5.6):
http://jsfiddle.net/TIBCO_JS_Community/sozzq0sL/embedded/
Api samples (6.1):
http://community.jaspersoft.com/wiki/visualizejs-api-samples-v61
Api samples (5.6):
http://community.jaspersoft.com/wiki/visualizejs-api-notes-and-samples-v56
Really hope this will help someone new to Jaspersoft & visualize.js like me.
I'm trying to use the last.fm API in javascript but I can't get it working. I found this GitHub reference which I thought would be useful: https://github.com/fxb/javascript-last.fm-api
var cache = new LastFMCache();
but this ^ causes an error "ReferenceError: LastFMCache is not defined." I've tried putting the files from https://github.com/fxb/javascript-last.fm-api in the same directory as the file I'm running. I'm running it with node.js - I don't know if that would be a problem. Running the file with node.js before was not a problem though. Any idea how I can remedy this problem? I can't tell if I'm missing some code or my files are in the wrong directory. Thanks for your help!
You are using client-side JavaScript library.
If you will browse the NPM, there are plenty of Last.fm modules, the most popular is simple-lastfm
Here is the example taken from the docs:
var Lastfm = require('simple-lastfm');
var lastfm = new Lastfm({
api_key: 'xxx',
api_secret: 'xxx',
username: 'xxx',
password: 'xxx'
});
lastfm.getSessionKey(function(result) {
console.log("session key = " + result.session_key);
if(result.success) {
lastfm.scrobbleNowPlayingTrack({
artist: 'Ratatat',
track: 'Seventeen Years',
callback: function(result) {
console.log("in callback, finished: ", result);
}
});
} else {
console.log("Error: " + result.error);
}
});