我正在尝试实现以下逻辑:
用户打开我的网站页面并单击按钮
弹出窗口显示要求同意将文件上传到他的Google驱动器
用户同意,我获取了auth_code,获取访问权限并刷新令牌
以后有必要时,我将一些文档上传到他的Google驱动器中,不再征求权限。
前三点终于奏效了。客户端上的代码(ReactJS):
componentWillMount() {
let script = document.createElement('script');
script.setAttribute('id', 'google_script');
const self = this;
script.onload = function() {
gapi.load('auth2', ()=>{
const clientId = window.googleClientId;
const scope = 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file';
let config = {
clientId: clientId,
scope: scope
};
self.googleAuth = gapi.auth2.init(config);
});
};
script.src = "https://apis.google.com/js/platform.js";
document.getElementsByTagName('head')[0].appendChild(script);
};
//然后
buttonClick(){
this.googleAuth.grantOfflineAccess().then((data)=>{ //<== Offline access
if (data.code){
this.saveGoogleDriveToken(data.code); //<-- Sends to the server
} else {
}
});
}
服务器端,将代码交换为令牌。
def get_tokens(auth_code):
json_path = os.path.join(static_folder_path, "client_secrets.json")
credentials = None
try:
credentials = client.credentials_from_clientsecrets_and_code(
json_path,
scopes,
auth_code)
except Exception as ex:
print(ex)
return None
return {
'access_token': credentials.access_token,
'refresh_token': credentials.refresh_token
}
我将这两个令牌保存在数据库中。稍后,当我要上传文档时:
credentials = google.oauth2.credentials.Credentials(user_access_token,
refresh_token = user_refresh_token,
token_uri = 'https://oauth2.googleapis.com/token',
client_id = get_config_var('GOOGLE_CLIENT_ID'),
client_secret = get_config_var('GOOGLE_CLIENT_SECRET')
)
drive_service = build('drive', 'v3', credentials=credentials)
fd = io.BytesIO(invoice_file_bytes)
body = {'name': invoice_file_name, 'mimeType': 'application/pdf'}
media_body = MediaIoBaseUpload(fd = fd, mimetype='application/pdf')
file = drive_service.files().create(body=body,
media_body=media_body,
fields='id').execute() #<== When hit here
但是我无法使其正常工作。在用户同意后不久,它就开始工作了,但不到1个小时(我认为访问令牌已过期)就可以了。我所拥有的是'invalid_client:Unauthorized','{\ n“ error”:“ invalid_client”,\ n “ error_description”:“未经授权” \ n}')
我读过google api可以自行刷新访问令牌,但我不知道如何使它工作。
credentials = google.oauth2.credentials.Credentials(user_access_token,
refresh_token = user_refresh_token,
token_uri = 'https://oauth2.googleapis.com/token',
client_id = get_config_var('GOOGLE_CLIENT_ID'),
client_secret = get_config_var('GOOGLE_CLIENT_SECRET')
)
http = cred.authorize(httplib2.Http())
credentials.refresh(http)
drive_service = build('drive', 'v3', credentials=credentials)
fd = io.BytesIO(invoice_file_bytes)
body = {'name': invoice_file_name, 'mimeType': 'application/pdf'}
media_body = MediaIoBaseUpload(fd = fd, mimetype='application/pdf')
file = drive_service.files().create(body=body,
media_body=media_body,
fields='id').execute() #<== When hit here