2016-12-29 16 views
0

私は同様の質問をたくさん読んでいますが、私にとって受け入れられる回答は見つかりませんでした。ドライブREST APIはファイルが1MBを超えると400を返します

私は、成功したビルドの後に、gradleがAndroidの.apkファイルをアップロードするための簡単なドライブアップロードタスクを書いています。私はDrive Java APIを使用せず、REST要求のみを使用します。

このタスクは、トークン取得:

task getToken << { 
    def keyStoreFile = file("SomeProject-PrivateKey.p12") 
    def keyStorePass = "notasecret" 
    def serviceAccountEmail = "[email protected]" 

    def keyStore = java.security.KeyStore.getInstance("PKCS12") 
    keyStore.load(keyStoreFile.newInputStream(), keyStorePass.toCharArray()) 
    def privateKey = keyStore.getKey(keyStore.aliases().nextElement(), keyStorePass.toCharArray()) 

    def JWTHeader = '{"alg":"RS256","typ":"JWT"}' 
    def JWTClaimSet = '{\n' + 
     ' "iss":' + serviceAccountEmail + ',\n' + 
     ' "scope":"https://www.googleapis.com/auth/drive",\n' + 
     ' "aud":"https://www.googleapis.com/oauth2/v4/token",\n' + 
     ' "exp":' + (System.currentTimeSeconds() + 5 * 60) + ',\n' + // + 5 minutes 
     ' "iat":' + System.currentTimeSeconds() + '\n' + 
     '}' 
    def JWT = new String(Base64.urlEncoder.encode(JWTHeader.bytes)) + 
     '.' + new String(Base64.urlEncoder.encode(JWTClaimSet.bytes)) 

    def signature = java.security.Signature.getInstance("SHA256withRSA") 
    signature.initSign(privateKey) 
    signature.update(JWT.bytes) 
    JWT += '.' + new String(Base64.urlEncoder.encode(signature.sign())) 

    System.out.print "assertion: " + JWT + "\n" 

    def authUrl = new URL("https://www.googleapis.com/oauth2/v4/token") 
    HttpURLConnection auth = authUrl.openConnection() 
    auth.setRequestMethod("POST") 
    auth.setRequestProperty("Host", "www.googleapis.com") 
    auth.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") 
    auth.setDoOutput(true) 
    def body = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer' + 
     '&assertion=' + JWT 
    auth.outputStream.write(body.bytes) 
    def reader = new BufferedReader(new InputStreamReader(auth.inputStream)) 

    StringBuilder sb = new StringBuilder() 
    for (int c; (c = reader.read()) >= 0;) 
    sb.append((char) c) 
    System.out.println(sb.toString()) 
} 

そして、この1つのアップロードいくつかのパブリックフォルダへのファイルまたは[email protected]で共有フォルダ:小さなファイルの場合

task uploadToDrive << { 
    File apk = file("test1.txt") 
    // File apk = file("test2.apk") 
    def url = new URL("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"); 

    HttpURLConnection drive = url.openConnection(); 
    drive.setRequestMethod("POST") 
    drive.setRequestProperty("Host", "www.googleapis.com") 
    drive.setRequestProperty("Authorization", "Bearer " + "ya29.ElnDA_idxn6dL4cji6Oh3dQbdCaMGtGfmIMwIDa4yrEgiL9G8I6qHeSoCNUwcfYESZiLBBaymYLWJQBuTgypqyOy_YVUNpwyd2Gf8rYLgAsSksNnruygoFBS9g") 
    drive.setRequestProperty("Content-Type", "multipart/related; boundary=foo_bar_baz") 

    String body = '\n' + 
     '--foo_bar_baz\n' + 
     'Content-Type: application/json; charset=UTF-8\n\n' + 
     '{\n' + 
     ' "name": "TEST",\n' + 
     ' "parents": [ "0BzkpQECQo2d2SEo5OTd4RHpnOFE" ]\n' + 
     '}\n\n' + 
     '--foo_bar_baz\n' + 
     'Content-Type: application/octet-stream\n\n' 
    String end = '--foo_bar_baz--' 

    drive.setFixedLengthStreamingMode(body.bytes.length + apk.length() + end.bytes.length)  // Content Length 

    drive.setDoOutput(true) 
    drive.setDoInput(true) 
    drive.outputStream.write(body.bytes) 
    apk.withInputStream { is -> 
    def buffer = new byte[1024]; 
    int len; 
    while ((len = is.read(buffer)) != -1) { 
     drive.outputStream.write(buffer, 0, len); 
    } 
    } 
    drive.outputStream.write(end.bytes) 

    def reader = new BufferedReader(new InputStreamReader(drive.inputStream)) 
    StringBuilder sb = new StringBuilder() 
    for (int c; (c = reader.read()) >= 0;) 
    sb.append((char) c); 
    System.out.println(sb.toString()) 
} 

それはうまく動作します!しかし、実際の.apkファイルや〜1Mbイメージをアップロードしようとすると、gradleは失敗します:

タスク 'uploadToDrive'の実行に失敗しました。 サーバー返されたHTTPレスポンスコード:400 URLについて:https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart

任意のアイデア?

+0

公式アドバイスは大容量のファイルのためのマルチパートアップロードを使用しないことです。これは特にモバイルの場合に当てはまります。再開可能なアップロードを使用する必要があります。私はこれが400を説明するかどうかわかりませんが、とにかくやっていなければならないことです。 – pinoyyid

+0

エラー応答が発生した場合の解決方法については、[Handling API Errors](https://developers.google.com/drive/v3/web/handle-errors)を参照してください。また、[resumable upload](https://developers.google.com/drive/v3/web/manage-uploads#resumable)を使用して、同じエラーが発生するかどうかを確認してください。最後に、関連する[SO post](http://stackoverflow.com/a/24459799/5995040)を確認したい場合があります。アンドロイド固有のAPIを使用すると、このすべてが処理されます。 –

+0

GoogleのGitHub - [GoogleドライブAndroid APIデモ](https://github.com/googledrive/android-demos)とチュートリアル - [AndroidでGoogleドライブを統合する](https://www.numetriclabz。 co.jp/integrate-google-drive-in-android-tutorial /)をご覧ください。これは、AndroidでのGoogleドライブのコード実装を理解するのに役立ちます。この情報が役立つことを願っています。 –

答えて

0

本当に答えは(なぜ400?)ですが、問題を解決します。 ありがとうございましたMr.Rebot & pinoyyid

作品大きなファイルのこと再開可能アップロードの例:

task uploadResumable << { 
    File apk = file("dog.jpg") 
    def url = new URL("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable"); 

    HttpURLConnection drive = url.openConnection(); 
    drive.setRequestMethod("POST") 
    drive.setRequestProperty("Host", "www.googleapis.com") 
    drive.setRequestProperty("Authorization", "Bearer " + "ya29.ElnDA_idxn6dL4cji6Oh3dQbdCaMGtGfmIMwIDa4yrEgiL9G8I6qHeSoCNUwcfYESZiLBBaymYLWJQBuTgypqyOy_YVUNpwyd2Gf8rYLgAsSksNnruygoFBS9g") 
    drive.setRequestProperty("Content-Type", "application/json; charset=UTF-8") 
    drive.setRequestProperty("X-Upload-Content-Type", "image/jpeg") 

    String body = '\n' + 
     '{\n' + 
     ' "name": "DOGresum",\n' + 
     ' "parents": [ "0BzkpQECQo2d2SEo5OTd4RHpnOFE" ]\n' + 
     '}\n\n'; 

    drive.setFixedLengthStreamingMode(body.bytes.length)  // Content Length 
    drive.setDoOutput(true) 
    drive.setDoInput(true) 
    drive.outputStream.write(body.bytes) 

    // response header example: 
    //  -> Location: [https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=AEnB...] 
    // get "Location" header 
    String loc = drive.getHeaderFields().get("Location") 

    // trim '[' and ']' brackets and get URL query 
    def query = new URL(loc[1..-2]).query 

    // find upload_id value 
    String uploadId; 
    query.split('&').each { 
    if (it.split('=')[0] == 'upload_id') 
     uploadId = it.split('=')[1] 
    } 

    // start new upload 
    def url2 = new URL("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" + uploadId); 
    HttpURLConnection drive2 = url2.openConnection() 
    drive2.setRequestMethod('POST') 
    drive2.setRequestProperty("Content-Type", "image/jpeg") 
    drive2.setFixedLengthStreamingMode(apk.bytes.length)  // Content Length 
    drive2.setDoOutput true 
    drive2.setDoInput true 
    drive2.outputStream.write apk.bytes 
} 
関連する問題