0

這裏是我的代碼來測試從谷歌驅動器在服務器端導出文件。無法導出爲服務器端的PDF格式的谷歌幻燈片

import logging 

from flask import Flask, render_template, request 

from googleapiclient.discovery import build 
from googleapiclient.http import MediaIoBaseDownload 
from oauth2client.client import AccessTokenCredentials 

import httplib2 
import io 


app = Flask(__name__) 


@app.route('/gdrive/selectcallback') 
def userselectioncallback(): 
    print "In user selection callback... " 

    code = request.args.get('user_token') 
    fileId = request.args.get('fileId') 

    credentials = AccessTokenCredentials(code, 
             'my-user-agent/1.0') 


    http = httplib2.Http() 
    http_auth = credentials.authorize(http) 

    drive_service = build('drive', 'v3', http=http_auth) 

    drive_request = drive_service.files().export(
     fileId=fileId, 
     mimeType='application/pdf') 
    fh = io.FileIO('test.pdf', 'wb') 
    downloader = MediaIoBaseDownload(fh, drive_request) 
    done = False 
    while done is False: 
     status, done = downloader.next_chunk() 
     print "Download %d%%." % int(status.progress() * 100) 

    return code 


if __name__ == '__main__': 
    # This is used when running locally. Gunicorn is used to run the 
    # application on Google App Engine. See entrypoint in app.yaml. 
    app.run(host='127.0.0.1', port=8090, debug=True) 

在Web客戶端,一旦用戶選擇從文件選擇一個文件時,JavaScript前端將調用/gdrive/selectcallback與令牌和文件ID以上Python代碼。

舉個例子,令牌看起來是這樣的:ya29.Glu5BG-LQJFqZ-e4uImMSxz-14iS41jVLfXk6rVKvAPjylCwhUh98ZJk1iIC5Eb49pTfflGnU6qE7uzK44AYr0Wn79QMUkF368WFaYrhidrvpVjcsJSZ9P1M8VU6和文件ID看起來像這樣1ON9kGyb02TFCygy8jeIYyo2BKj5SzKgAP0xi5Rm08D4

下面是相關前端代碼(在CoffeeScript中):基於

pickerCallback =() -> 
    view = new google.picker.View(google.picker.ViewId.PRESENTATIONS) 
    picker = new google.picker.PickerBuilder() 
     .enableFeature(google.picker.Feature.NAV_HIDDEN) 
     .setAppId('zeetings') 
     .setOAuthToken(oauthToken) 
     .addView(view) 
     .setDeveloperKey(env['googleapi-client'].apiKey) 
     .setCallback(selectCallback) # The callback calls the python backend 
     .build() 
    picker.setVisible true 

    selectCallback = (data) -> 
    if data.action is google.picker.Action.PICKED 
     fileId = data.docs[0].id 
     fileSelectedCallback(fileId, oauthToken) if fileSelectedCallback 

調試信息,我的python代碼發出這兩個https調用:

2017-09-01 11:32:38,810 pid 260 tid 140546358265600 INFO
discovery URL being requested: GET https://www.googleapis.com/discovery/v1/apis/drive/v3/rest

2017-09-01 11:32:39,009 pid 260 tid 140546358265600 INFO discovery URL being requested: GET https://www.googleapis.com/drive/v3/files/1ON9kGyb02TFCygy8jeIYyo2BKj5SzKgAP0xi4Rm08D4/export?mimeType=application%2Fpdf

如果我使用第二個url直接在一個br owser,我得到以下錯誤:

{ 
"error": { 
    "errors": [ 
    { 
    "domain": "usageLimits", 
    "reason": "dailyLimitExceededUnreg", 
    "message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.", 
    "extendedHelp": "https://code.google.com/apis/console" 
    } 
    ], 
    "code": 403, 
    "message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." 
} 
} 

(我不認爲上述錯誤信息實際上反映了根本原因。它更可能是由於這樣的事實,呼叫沒有在我的瀏覽器進行身份驗證。)

我懷疑我必須使用google-auth庫(https://google-auth.readthedocs.io/en/latest/user-guide.html#making-authenticated-requests),但我不知道怎樣才能嫁給google-auth到Python代碼我有以上。我想我可以通過

from google.oauth2 import service_account 

credentials = service_account.Credentials.from_service_account_file(
    '/path/to/key.json') 

獲得證書,但我應該怎麼做在此之後,credentials?我是否用它來完全替代credentials = AccessTokenCredentials(code,'my-user-agent/1.0')

P.S.

根據@ Tanaike的建議,我嘗試直接使用API​​ url。這是我得到的結果:

{ 
"error": { 
    "errors": [ 
    { 
    "domain": "global", 
    "reason": "fileNotDownloadable", 
    "message": "Only files with binary content can be downloaded. Use Export with Google Docs files.", 
    "locationType": "parameter", 
    "location": "alt" 
    } 
    ], 
    "code": 403, 
    "message": "Only files with binary content can be downloaded. Use Export with Google Docs files." 
} 
} 

這似乎是一個V3的API問題。如果我切換到v2並使用downloadUrl鏈接,我可以下載PDF格式的文件。

+0

你從導出API得到了什麼錯誤消息?通過API瀏覽器導出似乎工作正常 –

+0

它發生在問題中提到的特定幻燈片(也提供了鏈接)。 「下載0%」被打印出來很多時間,直到最後抓到一個500. –

+0

您可能想要檢查這個報告爲[issue](https://issuetracker.google.com/issues/64294118)哪個Drive API返回錯誤500 。目前尚不清楚它是否正在爲v3工作,因爲報告只證實它在v2中工作。您可能想要關注該問題,然後發表評論/創建一個新問題。希望得到這個幫助 –

回答

0

User @Tanaike給了我很多好的建議來調試這個問題。我能夠直接測試REST API,以驗證1)我有正確的訪問代碼,並且2)驅動器v3文件導出API按預期工作

原來,問題出在MediaIoBaseDownload類。如果我從代碼中刪除它,只是直接接收數據:

data = drive_service.files().export(
     fileId=fileId, 
     mimeType='application/pdf').execute() 
f = open('test.pdf) 
f.write(data) 
f.close() 

那麼它將按預期工作