Opening specific MimeTypes with google picker - google-drive-api

I am working with realtime API and I am making use of realtime-client-utils.
Using existing code, I am creating realtime files with this method:
createRealtimeFile = function(title, callback) {
gapi.client.load('drive', 'v2', function() {
gapi.client.drive.files.insert({
'resource': {
mimeType: rtclient.REALTIME_MIMETYPE,
title: title
}
}).execute(callback);
});
}
and then I am trying to open files with this picker:
var popupOpen = function () {
var token = gapi.auth.getToken().access_token;
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes(rtclient.REALTIME_MIMETYPE+ "."+realTimeOptions.appId);
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.setAppId(realTimeOptions.appId)
.setOAuthToken(token)
.addView(view)
.addView(new google.picker.DocsUploadView())
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
};
Although if I use the setMimeTypes, no documents are found. If I remove that filter, my documents appear normally(along with every time of document in the drive). THe mime type I am using is the default one:
rtclient.REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk';
I am adding the appID as this is how its done on realtime-playground. I also tried without the "." or the appID but no documents are found.
Any suggestions about how to fix the filter ?

You should look for mimeType you created with.
You created your file with mimeType rtclient.REALTIME_MIMETYPE and you're looking for files with mimeType rtclient.REALTIME_MIMETYPE+ "."+realTimeOptions.appId That is the reason why you're not getting any files.
Change filepicker code to:
view.setMimeTypes(rtclient.REALTIME_MIMETYPE);
And make sure you change
rtclient.REALTIME_MIMETYPE = 'application/{{YOURE_CUSTOM_MIMETYPE}}';
to avoid collision with other apps.

Found the answer on an android forum. I had to create files with this mimeType:
REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk.'+appID;
and use same mimeType on view :
view.setMimeTypes(REALTIME_MIMETYPE);

Short answer: correct your appID. It is the first part of your CLIENT-ID. That is, if your client-id is 1088706429537-4oqhqr7o826ditbok23sll1rund1jim1.apps.googleusercontent.com, your APP_ID is 1088706429537. I initially confused it with the project-id and had your problem.
I started new answer because all accepted ones are wrong since they disregard the main issue. Might be they are right advising to change the mime-type to something completely custom. Yet, the most popular answer says that
You created your file with mimeType rtclient.REALTIME_MIMETYPE and
you're looking for files with mimeType rtclient.REALTIME_MIMETYPE+
"."+realTimeOptions.appId
This is seems natural but wrong fact. The topic author is right reproducing the demos. Google demos seem to do exactly that: they create application/vnd.google-apps.drive-sdk file and look for appid-expanded ones. This is correct actually because whenever you create a REALTIME_MIMETYPE=application/vnd.google-apps.drive-sdk file, google drive silently fixes file type! It expands it with .APP_ID. This also means that you do not need to customize your mime-type, as other answers propose. You can proceed with application/vnd.google-apps.drive-sdk, I suppose. I have checked: Google will even fix your mime type if some letters are misspelled, which makes the proposed customization even harder. Google API will take another mime type only if it is too different from REALTIME one. But I am not sure that this is a right thing to do, despite this is proposed by all other accepted answers as 'solution' because I do not know about the difference this implies. Nevertheless,
to to tie up, the reasons to use application/vnd.google-apps.drive-sdk instead of proposed custom types are:
This standard type is proposed by Google in realtime playground demos instead of custom type
Google calls this type 'REALTIME_MIMETYPE'. If your use something different, you use Realtime API to create non-realtime files. At least not that much realtime as proposed by google.
If you specify a different mime type, google still corrects it to REALTIME_MIMETYPE. This means that custom mime types are unwelcomed.
Proponents of customization do not understand anything of this. They even dare to laugh at Google official examples as 'ridiculous'. They basically say that we should not trust them.

Related

How to force / set locale in PDF.js

I'm upgrading from an old version of PDF.JS (1.9.426) to the latest stable (2.5.207).
Previously, it was very simple to force the locale to match your applications current locale.
You simply pass it through as a parameter in the URL;
/PDFJS/web/viewer.html?file=example.pdf #locale=zh-CN
However, on upgrading, I see that this is no longer recommended.
This is despite the documentation still mentioning it.
In my application, users can override their prefered locale, so it might not match the browser.
I've looked into embed / object, which seemed like the solution, until I realised Android browsers don't support embedded PDF viewing.
I've been searching for the correct way to implement this, and so far I've not found a good or recommended answer.
It seems PDF.js is still the best all round solution, but I can't figure out the correct way of using it to simply render an existing PDF into a div.
From what I can tell the developers simply removed the option, didn't upgrade the docs, and are recommending to hard code the locale in viewer.js (which to me, kind of defeats the point).
I'm hoping someone can point me in the correct direction, and possibly help others who come across this.
For anyone looking to just get this working (until a better answer comes along), heres a fix;
Find the method "_initializeL10n" in viewer.js (line 552 in v2.5.207);
async _initializeL10n() {
this.l10n = this.externalServices.createL10n({
locale: _app_options.AppOptions.get("locale")
});
const dir = await this.l10n.getDirection();
document.getElementsByTagName("html")[0].dir = dir;
}
Change it to this;
async _initializeL10n() {
var hash = document.location.hash.substring(1);
var hashParams = (0, _ui_utils.parseQueryString)(hash);
this.l10n = this.externalServices.createL10n({
locale: ('locale' in hashParams) ? hashParams['locale'] : _app_options.AppOptions.get("locale")
});
const dir = await this.l10n.getDirection();
document.getElementsByTagName("html")[0].dir = dir;
}
This takes the code we need from the old version and gets #locale= working.
I hope to be told the correct way of doing it at some point.

Creating a Google Sheet in a specific folder with DriveApp

I want to create a Google Sheet in a specific folder on Google Drive using Google Apps Script. According to the documentation of the File class:
createFile(name, content, mimeType)
Creates a file in the current folder with the given name, contents, and MIME type. Throws an exception if content is larger than 10MB.
// Create an HTML file with the content "Hello, world!"
DriveApp.getRootFolder().createFile('New HTML File', '<b>Hello, world!</b>', MimeType.HTML);
And according to the MimeType documentation:
Enum MimeType
An enumeration that provides access to MIME-type declarations without typing the strings explicitly. Methods that expect a MIME type rendered as a string (for example, 'image/png') also accept any of the values below, so long as the method supports the underlying MIME type.
There is no mention of createFile supporting only a subset of available MIME types. The page includes a table, which includes this MIME type:
GOOGLE_SHEETS Enum Representation of MIME type for a Google Sheets file.
My issue lies in implementing this method of creating a file as described in the File documentation.
var folder = DriveApp.createFolder('new folder');
var ss = folder.createFile('new sheet', '', MimeType.GOOGLE_SHEETS);
This will throw an error, stating
Invalid argument: file.contentType (line 2, file "Code")
Replacing MimeType.GOOGLE_SHEETS with the string application/vnd.google-apps.spreadsheet obviously did not help. I am aware of this question, but the accepted answer simply admits defeat and uses a common messy workaround by creating the file in SpreadsheetApp, copying it, and deleting the original. This question has a similarly disappointing accepted answer to the same problem, except for Google Docs. The SpreadsheetApp workaround is fine, but I'm hoping 3 years on that someone holds the answer as to how to use createFile properly.
The Google issue tracker has a long, long history of this question being asked. Way back in 2014, a Google staff member declared that it was a resolved issue, and they had decided that MimeType.GOOGLE_-type files could not be created by the createFile method.
Marked as fixed.
After extensive consideration, we have determined that DriveApp.createFile() should not be used to create MimeType.GOOGLE_* files.
Shortly, attempting to do so will fail and result in a more descriptive error message.
Unfortunately, despite promising otherwise, the error message was never changed and the documentation was never updated to reflect this "extensive consideration".
The correct solution to add a MimeType.GOOGLE_-type file to a specific folder with 1 server call (no copying, removing, or updating) is
var folder = DriveApp.createFolder('folder');
var file = {
title: 'New Sheet',
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: folder.getId()}]
}
ssId = Drive.Files.insert(file).id;
Drive.Files.insert does require the Advanced Drive Service, which you can enable on your script with this guide.
Try this:
function createFolderAndFile() {
var folder = DriveApp.createFolder('RootSub');
var file = SpreadsheetApp.create('RootSubSheet');
Drive.Files.update({"parents": [{"id": folder.getId()}]}, file.getId());
}

Program-generated KML file validates, but doesn't work

I had a co-worker that normally worked with Google Maps and now I am creating my first map. I am using what they developed in the past and making the changes for what I need. They created a script that sets some of the map defaults, so that is why things might look slightly different.
var map = new Map();
map.loadMap();
var kml = new google.maps.KmlLayer({ url: 'http://api.mankatomn.gov/api/engineeringprojectskml', suppressInfoWindows: true });
kml.setMap(map.map);
The map loads. My KML file doesn't load. I don't get any errors in the console. When I replace the url with a different URL http://www.mankato-mn.gov/Maps/StreetConstruction/streetconstruction.ashx?id=122 it'll work just fine. My new feed does validate. Is there a issue with my web service?
Update: After a few days, I am still having the issue. So I am pretty sure this isn't a DNS issue anymore. I created a jsFiddle to see if it is my code or something else. I started with Google's sample code and changed the URL of the KML file to both my web service and to a static version of the generated file. Both are valid KML files. Neither work. If there was a syntax error, wouldn't the API report that?
You can get the status of a KML layer with
kml.getStatus();
which in this case return:
"INVALID_DOCUMENT"
Now, if I request your URL from the browser, I get
<Error>
<Message>An error has occurred.</Message>
</Error>
So it seems if there ever was a valid KML there, it isn't anymore. Assuming from your question I can oly guess it was above weight limit, or you weren't associating it with a valid instance of map.
For getStatus to return something useful, you must wait for Google Maps API to try and load the KML layer you declared. For example, you can add a listener on the status_changed event.
var kmloptions={
url: 'https://dl.dropboxusercontent.com/u/2732434/engineeringprojectskml.kml',
suppressInfoWindows: true
};
var newKml = new google.maps.KmlLayer(kmloptions);
newKml.setMap(map);
google.maps.event.addListenerOnce(newKml, 'status_changed', function () {
console.log('KML status is', newKml.getStatus());
});
in this case (note that I'm using the alternative URL you used in the jsFiddle), I still get INVALID DOCUMENT.
Update: it seems the problem was the encoding of the file (UTF-16 BE is meant to be binary). I converted it to utf-8 and reindented (it's in my public dropbox now)
You can check if the DNS is setup by:
Going to the url in your browser. Do this with cache emptied and history ereased (private mode is best). If it ends up at your server and the right file it is not a DNS problem.
Move the file to a location you're sure it is reachable without any DNS issues. e.g. http://www.mankato-mn.gov/Maps/StreetConstruction/engineeringprojectskml
If the problem persists make sure that your KML syntax and Javascript is 100% correct. Also check out https://developers.google.com/maps/documentation/javascript/examples/layer-kml if you're still having any issues.

DocsUploadView and setOAuthToken causing "undefined Dismiss" error

I'm building a webapp where a user can Authorize via OAuth2 and choose/upload files from their own Drive for later use. Essentially we're just storing the file ID and using the API to access them later. Everything is working fine when I use .setAuthUser() and require users to be logged in independent of our app, but when we use .setOAuthToken() instead only the file picker works — the DocsUploadView panel returns an "undefined" error.
This behavior is consistent across Firefox/Chrome/Safari and with or without a current user login. It's always able to see files, never able to upload them. We are requesting full drive scope but even with that we're seeing errors.
For now we're just using setAuthUser as a workaround but this causes extra steps and a few problems when a user isn't logged in. Is it possible to use setOAuthToken with DocsUploadView?
The picker builder code I'm using is below, with IDs and tokens in the same format I'm using but altered for security.
Thanks!
var view = new google.picker.View(google.picker.ViewId.DOCS);
var uploadview = new google.picker.DocsUploadView();
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.MINE_ONLY)
.disableFeature(google.picker.Feature.NAV_HIDDEN)
.disableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId('987654321098')
.setOAuthToken('ya31.AIER6DRhxRgRsT0SoGPoaxPMhDd0n3OHKj43SJaG5kFndZ52')
.addView(uploadview)
.addView(view)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
[cross-posted at: https://groups.google.com/d/topic/google-picker-api/p9whgDscUrQ/discussion]
The Picker API doesn't currently support uploads using OAuth tokens. I filed an internal feature request for this to be implemented, but for the moment you should keep relying on your workaround.
This even SOUNDS stupid, but what about order of execution in the chaining?
.addView(uploadview)
.addView(view)
becomes
.addView(view)
.addView(uploadview)
Another thing I might suggest here is to enable multi_select on the picker
enableFeature(google.picker.Feature.NAV_HIDDEN)
enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
, just to test that there's not a bug in dependency on either of those features.

Chrome extension : Download/export content created "on the fly"

I need to let the user to download a file created on the fly from some data contained in the extension, but I don't want to do this server-side.
As a real-world example : There is a variable containing the text "hello world". I want the user to be able to download/create a .TXT file containing such text.
Is it possible ?
-edited Oct 30, 2010-
Solutions so far:
window.saveAs - not working at all
createObjectURL - works, but the filename and other options can't be customized yet
copy data to clipboard - works, but too many steps are required to the user
create a GoogleDocs document - could work, but needs messing with the API and Oauth
-edited Apr 15, 2011
Looks like things are improving: https://github.com/eligrey/FileSaver.js
But Chrome 14+ is still a bit weird about filenames.
I think the only way is to call save dialog through flash, see Downloadify library.
In the Chromium-extensions Google Group I have found this working example: (I have modified it to work from the pop-up)
BuiltBlob = new BlobBuilder("");
BuiltBlob.append("Hello, world");
BlobToSave = BuiltBlob.getBlob();
chrome.tabs.create({'url': createObjectURL(BlobToSave), 'selected': false});
But the filename is not set, ending with something like cf8a56bf-d724-4b97-b10f-e252961135bd
On the The W3C docs ( http://dev.w3.org/2009/dap/file-system/file-writer.html ) I've found this not working example:
var bb = new BlobBuilder();
bb.append("Lorem ipsum");
var fileSaver = window.saveAs(bb.getBlob(), "test_file");
fileSaver.onwriteend = myOnWriteEnd;
but window.saveAs doesn't appear to exists.
Googleing around I've found outdated Google Gears references, but nothing else, maybe because I'm dealing with something too new to have proper documentation ?
Is there a way to set the filename/mime-type to the first example?
I don't think this is possible because of safety reasons