我有一个列出工作的移动网站,用户申请并上传他们的简历(简历) - 我希望他们能够从他们的Google云端硬盘中选择一个文件。
我在这里创建了Hello world示例 - https://developers.google.com/picker/docs/(为方便起见,此处转载的代码)
问题是,如果尚未登录到云端硬盘,则会启动登录弹出窗口。这在桌面上已经糟糕了,但在手机上确实很糟糕。
我尝试了this solution,但得到'TypeError:gapi.auth未定义'
我还尝试从onclick事件启动选择器,而不是文档中描述的onload。
function launchDrive()
{
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
<input type='button' value='Launch Drive' onclick='launchDrive();'>
Google代码示例:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
var developerKey = 'xxxxxxxYYYYYYYY-12345678';
var clientId = "1234567890-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com"
var scope = ['https://www.googleapis.com/auth/photos'];
var pickerApiLoaded = false;
var oauthToken;
function onApiLoad() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for picking user Photos.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var picker = new google.picker.PickerBuilder().
addView(google.picker.ViewId.PHOTOS).
setOAuthToken(oauthToken).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
</script>
</head>
<body>
<div id="result"></div>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
2015年5月13日编辑
继Jason的回答之后,我也尝试了这一点(通过oncllick按钮调用):
function launchDrive()
{
//gapi.load('auth', {'callback': onAuthApiLoad});
gapi.auth.init(onAuthApiLoad);
gapi.load('picker', {'callback': onPickerApiLoad});
}
答案 0 :(得分:2)
您需要调用gapi.auth.init。请参阅此处的文档:https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauthinit
初始化授权功能。在客户端加载时调用此方法以防止弹出窗口阻止程序阻塞gapi.auth.authorize调用上的auth窗口。
答案 1 :(得分:1)
我现在有效。
在选择器的示例https://developers.google.com/picker/docs/中,它调用:
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
在此示例https://developers.google.com/api-client-library/javascript/start/start-js中,它调用:
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
使用client.js修复'TypeError:gapi.auth is undefined'问题,因此登录弹出窗口有效。
也许api.js是API的旧版本?
答案 2 :(得分:1)
要解决您的问题,您需要了解google如何在您的案例中执行oauth:
为什么浏览器在第二步阻止弹出窗口:
window.event
被销毁)。因此,如果用户没有阻止弹出窗口并且您的弹出窗口仍然被阻止,则gapi操作看起来像:
<input type="button" onclick="auth" value="click"/>
function auth() {
setTimeout(function() {
// by this time window.event is destroyed, that's why browser blocks the popup
window.open(document.URL, '_blank', 'location=yes,height=570,width=520,scrollbars=yes,status=yes');
}, 100)
}
那么你应该做什么:
window.event
将不为空。因此,将所有gapi init方法移至DOMContentLoaded
。答案 3 :(得分:0)
跳到最底层
这是目前适用于我的代码。这是我使用这个API的第一个小时,所以我真的不知道这些函数是做什么的,我也不知道正确的顺序和错误处理是什么,但至少现在这个功能正常。也许它将来会帮助别人。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
</head>
<body style="width: 70%; margin: 100px auto;">
<!-- Added a button to open picker -->
<button onclick="loadPicker();" >Open from GoogleDrive</button>
<div id="result"></div>
<!-- Moved to end of body tag instead of head -->
<script type="text/javascript">
// The Browser API key obtained from the Google API Console.
// Replace with your own Browser API key, or your own key.
var developerKey = '<IDK WHAT'S SUPPOSED TO GO HERE, BUT ITS OK>';
// The Client ID obtained from the Google API Console. Replace with your own Client ID.
var clientId = "<YOUR CLIENT ID GOES HERE>.apps.googleusercontent.com"
// Replace with your own project number from console.developers.google.com.
// See "Project number" under "IAM & Admin" > "Settings"
var appId = "<YOUR APP ID GOES HERE>";
// Scope to use to access user's Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
// This needs to be client:auth2 no client
gapi.load('client:auth2', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
// we need to init gapi.client with the clientId and scope first
gapi.client.init({
clientId: clientId,
scope: scope
});
// Now we can authorize? seems like the same thing here
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for searching images.
function createPicker() {
// Wow this is a mess
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.addView(new google.picker.DocsUploadView())
// Guess this is... optional?
//.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
alert('Selected fileId: ' + fileId);
}
}
</script>
<!-- The Google API Loader script. Removed the autorun -->
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>
</body>
</html>
编辑:如果出现一个无法加载的弹出窗口,只需关闭它并再次单击该按钮即可。这解决了我刚才遇到的另一个问题。
同样,我不知道自己在做什么,所以希望我能更好地理解这一点并在以后澄清事情。
E2:啊,在Javascript GAPI文档页面上有关于OAuth2的更多信息,可在此处找到:https://developers.google.com/api-client-library/javascript/features/authentication
从另一个文档看,如果尚未加载,gapi.load('client', callback)
将加载auth2。拨打gapi.load('client:auth2', callback)
只会保存1个网络请求。
注意:使用Oauth 2.0授权应用程序时,您不需要像第一个示例中那样设置API密钥。但是,如果您的代码扩展到处理未经授权的请求,这是一个很好的做法。
这解释了为什么我可以删除API /开发人员密钥。
编辑3:好的,上面的代码在技术上是错误的。
警告:请勿在推荐的gapi.auth2.init和signIn流程旁边使用此方法。这是两种截然不同的行为(对gapi.auth2.authorize和gapi.auth2.init / signIn的身份验证的授权),如果在同一个应用程序中使用,则会出现意外问题。
autorize用于单次使用身份验证(例如,如果您登录了2个Google帐户)。使用gapi.init()
意味着更长期的会话(例如登录和退出网站)。
目前这是如何运作的,我不知道。
不要使用上面的代码,只想记录进度。这是一个使用getAuthResponse()
<html>
<head></head>
<body>
<div style="padding: 50px">
<h2 style="color: #2196f3;">Status: <span id='status'></span></h2>
<button id="signin-button" onclick="handleSignInClick()">Sign In</button>
<button id="signout-button" onclick="handleSignOutClick()">Sign Out</button>
<button id="signout-button" onclick="openFile()">Open File</button>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
var cid = '<CLIENTID_HERE>';
var scope = 'https://www.googleapis.com/auth/drive';
var authenticated = false;
var pickerLoaded = false;
var auth = null;
var user = null;
var response = null;
var token = null;
var stat = $('#status');
function openFile() {
gapi.load('client:auth2', initClient);
gapi.load('picker', onPickerLoad);
}
function initClient() {
stat.html("starting");
gapi.client.init({
clientId: cid,
scope: scope
}).then(
function () {
console.log("init");
// Check if we are logged in.
auth = gapi.auth2.getAuthInstance();
auth.isSignedIn.listen(onStatusChange);
authenticated = auth.isSignedIn.get();
stat.html(authenticated);
if (authenticated) {
stat.html("Logged In!");
user = auth.currentUser.get();
response = user.getAuthResponse(true);
token = response.access_token;
showPicker();
} else {
stat.html("Logged Out!");
}
}, function(){stat.html("error")});
}
function onStatusChange(isSignedIn) {
if (isSignedIn) {
stat.html("Logged In!");
authenticated = true;
user = auth.currentUser.get();
response = user.getAuthResponse(true);
token = response.access_token;
showPicker();
showPicker();
} else {
authenticated = false;
stat.html("Logged Out!");
}
}
function handleSignInClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignOutClick(event) {
gapi.auth2.getAuthInstance().signOut();
alert("signed out");
}
function onPickerLoad() {
pickerLoaded = true;
showPicker();
}
function showPicker() {
if (pickerLoaded && authenticated) {
var view = new google.picker.View(google.picker.ViewId.DOCS);
var picker = new google.picker.PickerBuilder();
picker.addView(view);
picker.enableFeature(google.picker.Feature.MULTISELECT_ENABLED);
picker.setOAuthToken(token);
picker.setAppId()
picker.setCallback(onDriveFileOpen);
picker = picker.build();
picker.setVisible(true);
}
}
function onDriveFileOpen(data) {
console.log(data);
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
console.log(fileId);
alert(data.docs[0].name);
}
}
</script>
<script async defer src="https://apis.google.com/js/api.js">
</script>
</body>
</html>