web-dev-qa-db-ja.com

Google Drive APIを使用してGoogle Driveから直接ダウンロード

Javaで書かれたデスクトップアプリケーションは、Googleドライブからパブリックファイルをダウンロードしようとします。私が見つけたように、ファイルのwebContentLinkを使用して実装できます(ユーザーの許可なしにパブリックファイルをダウンロードするためです)。

そのため、以下のコードは小さなファイルで機能します。

String webContentLink = aFile.getWebContentLink();
InputStream in = new URL(webContentLink).openStream();

ただし、この場合、ファイルはwebContentLinkを介して直接ダウンロードできません。Googleウイルススキャン警告が表示され、ユーザーの確認が必要です。例を参照してください: web content link

だから私の質問は、ユーザーの許可なしにGoogleドライブから公開ファイルのコンテンツを取得する方法ですか?

35
Philip Voronov

2015年12月8日更新Googleサポート を使用して

googledrive.com/Host/ID

メソッドは2016年8月31日にオフになります。


私はこの問題に出くわしました。

トリックは、Googleドライブフォルダをウェブホストのように扱うことです。

2015年4月1日更新

Googleドライブが変更され、ドライブに直接リンクする簡単な方法があります。参考のために以前の回答を下に残しましたが、ここに更新された回答があります。

  1. Googleドライブにパブリックフォルダーを作成します。

  2. このドライブを一般公開します。

    enter image description here

  3. そのフォルダーにいるときに、アドレスバーからフォルダーUUIDを取得します

    enter image description here
  4. このUUIDをこのURLに入れます

    https://googledrive.com/Host/<folder UUID>/
  5. ファイルがある場所にファイル名を追加します。

    https://googledrive.com/Host/<folder UUID>/<file name>

Googleが意図した機能です
新しいGoogleドライブリンク

あなたがしなければならないのは、単純にパブリック共有ドライブフォルダのHostURLを取得することです。これを行うには、プレーンHTMLファイルをアップロードし、GoogleドライブでpreviewホストURLを見つけます。

手順は次のとおりです。

  1. Googleドライブにフォルダーを作成します。

  2. このドライブを一般公開します。

    enter image description here

  3. 単純なHTMLファイルをアップロードします。追加のファイルを追加します(サブフォルダーはOK)

    enter image description here

  4. GoogleドライブでHTMLファイルを開いて「プレビュー」します

    enter image description here

  5. このフォルダーのURLアドレスを取得します

    enter image description here

  6. URLフォルダーベースから直接リンクURLを作成する

    enter image description here

  7. このURLは、大きなファイルの直接ダウンロードを許可する必要があります。

[編集]

追加するのを忘れました。サブフォルダーを使用してファイルを整理する場合は、URL階層で予想されるフォルダー名を使用するだけです。

https://googledrive.com/Host/<your public folders id string>/images/my-image.png


私がやろうとしていたこと

Virtual Box for Vagrantを使用してカスタムDebianイメージを作成しました。この「.box」ファイルを同僚と共有して、Vagrantfileに直接リンクを配置できるようにしました。

最後に、実際のファイルへの直接リンクが必要でした。

Googleドライブの問題

ファイルのアクセス権を公開して、 gdocs2direct ツールのようなものを使用するか、自分でリンクを作成することで直接アクセスリンクを作成/生成する場合:

https://docs.google.com/uc?export=download&id=<your file id>

Cookieベースの確認コードと「Googleはこのファイルをスキャンできませんでした」というプロンプトが表示されますが、wgetやVagrantfileなどの場合は機能しません構成。

生成されるコードは、GETクエリ変数...&confirm=###を文字列に追加する単純なコードですが、ユーザーごとに固有であるため、他のクエリ変数に対してコピー/貼り付けを行うことはできません。

ただし、上記の「Webページホスティング」メソッドを使用すると、そのプロンプトを回避できます。

それがお役に立てば幸いです!

62
jmbertucci

"このファイルはウイルスをチェックできません" intermezzoページに直面した場合、ダウンロードはそれほど簡単ではありません。

基本的に通常のダウンロードリンクを最初にダウンロードする必要がありますが、「ダウンロード」ページにリダイレクトされます。この最初のリクエストからのCookieを保存し、[とにかくダウンロード]ボタンが指すリンクを見つけ、このリンクを使用してファイルをダウンロードする必要がありますが、最初のリクエストから取得したCookieを再利用します。

CURLを使用したダウンロードプロセスのbashバリアントは次のとおりです。

curl -c /tmp/cookies "https://drive.google.com/uc?export=download&id=DOCUMENT_ID" > /tmp/intermezzo.html
curl -L -b /tmp/cookies "https://drive.google.com$(cat /tmp/intermezzo.html | grep -Po 'uc-download-link" [^>]* href="\K[^"]*' | sed 's/\&amp;/\&/g')" > FINAL_DOWNLOADED_FILENAME

ノート:

  • この手順は、おそらくGoogleが変更した後に機能しなくなります
  • grepコマンドはPerl構文(-P) そしてその \K「演算子」は、本質的には「\K一致した結果に。どのバージョンのgrepがこれらのオプションを導入したのかわかりませんが、古代またはUbuntu以外のバージョンにはおそらくないでしょう
  • a Javaソリューションはほぼ同じです。Cookieを処理できるHTTPSライブラリと、ニースのテキスト解析ライブラリを使用します。
35
Martin Pecka

これは古い質問であることは知っていますが、調査の結果、この問題の解決策を見つけることができなかったので、私がうまくいったことを共有しています。

私は自分のプロジェクトの1つにこのC#コードを記述しました。プログラムでスキャンウイルス警告をバイパスできます。コードはおそらくJavaに変換できます。

using System;
using System.IO;
using System.Net;

public static class FileDownloader
{
    private const string GOOGLE_DRIVE_DOMAIN = "drive.google.com";
    private const string GOOGLE_DRIVE_DOMAIN2 = "https://drive.google.com";

    // Normal example: FileDownloader.DownloadFileFromURLToPath( "http://example.com/file/download/link", @"C:\file.txt" );
    // Drive example: FileDownloader.DownloadFileFromURLToPath( "http://drive.google.com/file/d/FILEID/view?usp=sharing", @"C:\file.txt" );
    public static FileInfo DownloadFileFromURLToPath( string url, string path )
    {
        if( url.StartsWith( GOOGLE_DRIVE_DOMAIN ) || url.StartsWith( GOOGLE_DRIVE_DOMAIN2 ) )
            return DownloadGoogleDriveFileFromURLToPath( url, path );
        else
            return DownloadFileFromURLToPath( url, path, null );
    }

    private static FileInfo DownloadFileFromURLToPath( string url, string path, WebClient webClient )
    {
        try
        {
            if( webClient == null )
            {
                using( webClient = new WebClient() )
                {
                    webClient.DownloadFile( url, path );
                    return new FileInfo( path );
                }
            }
            else
            {
                webClient.DownloadFile( url, path );
                return new FileInfo( path );
            }
        }
        catch( WebException )
        {
            return null;
        }
    }

    // Downloading large files from Google Drive prompts a warning screen and
    // requires manual confirmation. Consider that case and try to confirm the download automatically
    // if warning Prompt occurs
    private static FileInfo DownloadGoogleDriveFileFromURLToPath( string url, string path )
    {
        // You can comment the statement below if the provided url is guaranteed to be in the following format:
        // https://drive.google.com/uc?id=FILEID&export=download
        url = GetGoogleDriveDownloadLinkFromUrl( url );

        using( CookieAwareWebClient webClient = new CookieAwareWebClient() )
        {
            FileInfo downloadedFile;

            // Sometimes Drive returns an NID cookie instead of a download_warning cookie at first attempt,
            // but works in the second attempt
            for( int i = 0; i < 2; i++ )
            {
                downloadedFile = DownloadFileFromURLToPath( url, path, webClient );
                if( downloadedFile == null )
                    return null;

                // Confirmation page is around 50KB, shouldn't be larger than 60KB
                if( downloadedFile.Length > 60000 )
                    return downloadedFile;

                // Downloaded file might be the confirmation page, check it
                string content;
                using( var reader = downloadedFile.OpenText() )
                {
                    // Confirmation page starts with <!DOCTYPE html>, which can be preceeded by a newline
                    char[] header = new char[20];
                    int readCount = reader.ReadBlock( header, 0, 20 );
                    if( readCount < 20 || !( new string( header ).Contains( "<!DOCTYPE html>" ) ) )
                        return downloadedFile;

                    content = reader.ReadToEnd();
                }

                int linkIndex = content.LastIndexOf( "href=\"/uc?" );
                if( linkIndex < 0 )
                    return downloadedFile;

                linkIndex += 6;
                int linkEnd = content.IndexOf( '"', linkIndex );
                if( linkEnd < 0 )
                    return downloadedFile;

                url = "https://drive.google.com" + content.Substring( linkIndex, linkEnd - linkIndex ).Replace( "&amp;", "&" );
            }

            downloadedFile = DownloadFileFromURLToPath( url, path, webClient );

            return downloadedFile;
        }
    }

    // Handles 3 kinds of links (they can be preceeded by https://):
    // - drive.google.com/open?id=FILEID
    // - drive.google.com/file/d/FILEID/view?usp=sharing
    // - drive.google.com/uc?id=FILEID&export=download
    public static string GetGoogleDriveDownloadLinkFromUrl( string url )
    {
        int index = url.IndexOf( "id=" );
        int closingIndex;
        if( index > 0 )
        {
            index += 3;
            closingIndex = url.IndexOf( '&', index );
            if( closingIndex < 0 )
                closingIndex = url.Length;
        }
        else
        {
            index = url.IndexOf( "file/d/" );
            if( index < 0 ) // url is not in any of the supported forms
                return string.Empty;

            index += 7;

            closingIndex = url.IndexOf( '/', index );
            if( closingIndex < 0 )
            {
                closingIndex = url.IndexOf( '?', index );
                if( closingIndex < 0 )
                    closingIndex = url.Length;
            }
        }

        return string.Format( "https://drive.google.com/uc?id={0}&export=download", url.Substring( index, closingIndex - index ) );
    }
}

// Web client used for Google Drive
public class CookieAwareWebClient : WebClient
{
    private class CookieContainer
    {
        Dictionary<string, string> _cookies;

        public string this[Uri url]
        {
            get
            {
                string cookie;
                if( _cookies.TryGetValue( url.Host, out cookie ) )
                    return cookie;

                return null;
            }
            set
            {
                _cookies[url.Host] = value;
            }
        }

        public CookieContainer()
        {
            _cookies = new Dictionary<string, string>();
        }
    }

    private CookieContainer cookies;

    public CookieAwareWebClient() : base()
    {
        cookies = new CookieContainer();
    }

    protected override WebRequest GetWebRequest( Uri address )
    {
        WebRequest request = base.GetWebRequest( address );

        if( request is HttpWebRequest )
        {
            string cookie = cookies[address];
            if( cookie != null )
                ( (HttpWebRequest) request ).Headers.Set( "cookie", cookie );
        }

        return request;
    }

    protected override WebResponse GetWebResponse( WebRequest request, IAsyncResult result )
    {
        WebResponse response = base.GetWebResponse( request, result );

        string[] cookies = response.Headers.GetValues( "Set-Cookie" );
        if( cookies != null && cookies.Length > 0 )
        {
            string cookie = "";
            foreach( string c in cookies )
                cookie += c;

            this.cookies[response.ResponseUri] = cookie;
        }

        return response;
    }

    protected override WebResponse GetWebResponse( WebRequest request )
    {
        WebResponse response = base.GetWebResponse( request );

        string[] cookies = response.Headers.GetValues( "Set-Cookie" );
        if( cookies != null && cookies.Length > 0 )
        {
            string cookie = "";
            foreach( string c in cookies )
                cookie += c;

            this.cookies[response.ResponseUri] = cookie;
        }

        return response;
    }
}

これは、2015年5月19日の時点で再び更新されているようです:

どのように動作するようになったか:

Jmbertucciの最近更新された回答のように、フォルダをすべての人に公開します。これは以前よりも少し複雑です。フォルダを[オン-Web上で公開]に変更するには、[詳細設定]をクリックする必要があります。

以前と同じようにフォルダーUUIDを見つけます-フォルダーに移動して、アドレスバーでUUIDを見つけます。

https://drive.google.com/drive/folders/<folder UUID>

それから

https://googledrive.com/Host/<folder UUID>

巨大なサブドメインを持つインデックスタイプのページにリダイレクトされますが、フォルダー内のファイルを表示できるはずです。次に、右クリックして目的のファイルへのリンクを保存できます(この直接リンクには、googledrive.com)。 wgetを使用して、私にとってはうまくいきました。

これは、他の共有フォルダでも機能するようです。

例えば。、

https://drive.google.com/folderview?id=0B7l10Bj_LprhQnpSRkpGMGV2eE0&usp=sharing

にマップ

https://googledrive.com/Host/0B7l10Bj_LprhQnpSRkpGMGV2eE

また、右クリックすると、これらのファイルへの直接リンクを保存できます。

3
Sean

#ケース1:小さいサイズのファイルをダウンロードします。

#ケース2:サイズの大きいファイルをダウンロードします。

  • 返されたウイルススキャン警告ページの壁に引っかかった。 html dom要素を解析することで、「とにかくダウンロード」ボタンの下に確認コード付きのリンクを取得しようとしましたが、機能しませんでした。 Cookieまたはセッション情報が必要な場合があります。 ここに画像の説明を入力

解決:

  • 最後に、上記の2つのケースの解決策を見つけました。 Jsonを取得するには、接続ステップにhttpConnection.setDoOutput(true)を配置するだけです。

    )]}' { "disposition":"SCAN_CLEAN", "downloadUrl":"http:www...", "fileName":"exam_list_json.txt", "scanResult":"OK", "sizeBytes":2392}

その後、Jsonパーサーを使用してdownloadUrl、fileName、sizeBytesを読み取ることができます。

  • フォロースニペットを参照してください。

    private InputStream gConnect(String remoteFile) throws IOException{
        URL  url = new URL(remoteFile);
        URLConnection connection = url.openConnection();
        if(connection instanceof HttpURLConnection){
            HttpURLConnection httpConnection = (HttpURLConnection) connection;
            connection.setAllowUserInteraction(false);
            httpConnection.setInstanceFollowRedirects(true);
            httpConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows 2000)");
            httpConnection.setDoOutput(true);          
            httpConnection.setRequestMethod("GET");
            httpConnection.connect();
    
            int reqCode = httpConnection.getResponseCode();
    
    
            if(reqCode == HttpURLConnection.HTTP_OK){
                InputStream is = httpConnection.getInputStream();
                Map<String, List<String>> map = httpConnection.getHeaderFields();
                List<String> values = map.get("content-type");
                if(values != null && !values.isEmpty()){
                    String type = values.get(0);
    
                    if(type.contains("text/html")){
                        String cookie = httpConnection.getHeaderField("Set-Cookie");
                        String temp = Constants.getPath(mContext, Constants.PATH_TEMP) + "/temp.html";
                        if(saveGHtmlFile(is, temp)){
                            String href = getRealUrl(temp);
                            if(href != null){
                                return parseUrl(href, cookie);
                            }
                        }
    
    
                    } else if(type.contains("application/json")){
                        String temp = Constants.getPath(mContext, Constants.PATH_TEMP) + "/temp.txt";
                        if(saveGJsonFile(is, temp)){
                            FileDataSet data = JsonReaderHelper.readFileDataset(new File(temp));
                            if(data.getPath() != null){
                                return parseUrl(data.getPath());
                            }
                        }
                    }
                }
                return is;
            }
        }
        return null;
    }
    

そして

   public static FileDataSet readFileDataset(File file) throws IOException{
        FileInputStream is = new FileInputStream(file);
        JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));

        reader.beginObject();
        FileDataSet rs = new FileDataSet();
        while(reader.hasNext()){
            String name = reader.nextName();
            if(name.equals("downloadUrl")){
                rs.setPath(reader.nextString());
            } else if(name.equals("fileName")){
                rs.setName(reader.nextString());
            } else if(name.equals("sizeBytes")){
                rs.setSize(reader.nextLong());
            } else {
                reader.skipValue();
            }
        }
        reader.endObject();
        return rs;

    }
3
Noi Doan

https://github.com/google/skicka

このコマンドラインツールを使用して、Googleドライブからファイルをダウンロードしました。 「はじめに」セクションの指示に従うだけで、数分でGoogleドライブからファイルをダウンロードできます。

1
ibrahim

サービスアカウントを使用するとうまくいく場合があります。

1
pinoyyid

リンクからダウンロードし、確認リンクを取得するために取得したページをスクレイピングしてからダウンロードすることを検討します。

「とにかくダウンロード」URLを見ると、ランダムに生成されたトークンと思われる追加のconfirmクエリパラメーターがあります。それはランダムです...そしておそらくあなたはそれを自分で生成する方法を考えたくないので、スクレイピングはサイトの仕組みについて何も知らずに最も簡単な方法かもしれません。

さまざまなシナリオを検討する必要がある場合があります。

0

プログラムで(ブラウザで開くリンクをユーザーに提供するのではなく)Google Drive APIを介してファイルをダウンロードする場合は、ここに記載されているように、downloadUrlの代わりにファイルのwebContentLinkを使用することをお勧めします:- https://developers.google.com/drive/web/manage-downloads

0
David