0

サーバー側のGoogleドライブからファイルをエクスポートするテスト用コードです。ウェブクライアント側でGoogleスライドをサーバー側で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) 

ユーザーがファイルピッカーからファイルを選択すると、JavaScriptのフロントエンドは、トークンと、ファイルIDと上記Pythonコードで/gdrive/selectcallbackを呼び出します。

例として、トークンは次のようになります。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コードは、これらの2つの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

私は直接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)を使用する必要が疑われるが、私はPythonコードIへgoogle-authと結婚するかどうかはわかりません上記のとおりです。私は

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

質問に記載されているような特定のスライド(リンク先も提供されています)が発生します。 "Download 0%"が何度も印刷されて、最後に500がキャッチされるまで –

+0

これは[issue](https://issuetracker.google.com/issues/64294118)として報告されており、Drive APIがエラー500を返す報告されたものがv2で動作していることが確認されて以来、現在v3で動作しているかどうかは不明です。あなたはその問題に従って、新しいコメント/コメントを作成したいかもしれません。このヘルプがほしい –

答えて

0

ユーザー@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() 

を予想通り、それは

関連する問題