wake-up-neo.com

Direkter Download von Google Drive über die Google Drive-API

Meine in Java geschriebene Desktop-Anwendung versucht, öffentliche Dateien von Google Drive herunterzuladen. Wie ich herausgefunden habe, kann es mithilfe von webContentLink implementiert werden (es ist für die Fähigkeit, öffentliche Dateien ohne Benutzerautorisierung herunterzuladen).

Der folgende Code funktioniert also mit kleinen Dateien:

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

Bei großen Dateien funktioniert dies jedoch nicht, da in diesem Fall die Datei nicht direkt über webContentLink heruntergeladen werden kann, ohne dass der Benutzer dies mit einer Google-Viren-Scan-Warnung bestätigt. Sehen Sie sich ein Beispiel an: Link zum Webinhalt .

Meine Frage ist also, wie Sie den Inhalt einer öffentlichen Datei von Google Drive ohne Nutzerberechtigung abrufen können.

35
Philip Voronov

Update 8. Dezember 2015 Laut Google Support mit dem

googledrive.com/Host/ID

die Methode wird am 31. August 2016 deaktiviert.


Ich bin gerade auf dieses Problem gestoßen.

Der Trick besteht darin, Ihren Google Drive-Ordner wie einen Webhost zu behandeln.

Update 1. April 2015

Google Drive hat sich geändert und es gibt eine einfache Möglichkeit, eine direkte Verknüpfung zu Ihrem Laufwerk herzustellen. Ich habe meine vorherigen Antworten unten als Referenz hinterlassen, aber hier ist eine aktualisierte Antwort.

  1. Erstellen Sie einen öffentlichen Ordner in Google Drive.

  2. Teile dieses Laufwerk öffentlich.

    enter image description here

  3. Rufen Sie Ihre Ordner-UUID in der Adressleiste ab, wenn Sie sich in diesem Ordner befinden

    enter image description here
  4. Tragen Sie diese UUID in diese URL ein

    https://googledrive.com/Host/<folder UUID>/
  5. Fügen Sie den Dateinamen hinzu, in dem sich Ihre Datei befindet.

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

Welche Funktionalität ist von Google vorgesehen
neuer Google Drive Link .

Sie müssen lediglich die Host URL für einen öffentlich freigegebenen Laufwerksordner abrufen. Dazu können Sie eine einfache HTML-Datei hochladen und eine Vorschau in Google Drive anzeigen, um Ihre Host-URL zu finden.

Hier sind die Schritte:

  1. Erstellen Sie einen Ordner in Google Drive.

  2. Teile dieses Laufwerk öffentlich.

    enter image description here

  3. Laden Sie eine einfache HTML-Datei hoch. Füge zusätzliche Dateien hinzu (Unterordner ok)

    enter image description here

  4. Öffnen und "Vorschau" der HTML-Datei in Google Drive

    enter image description here

  5. Rufen Sie die URL-Adresse für diesen Ordner ab

    enter image description here

  6. Erstellen Sie eine Direktlink-URL aus Ihrer URL-Ordnerbasis

    enter image description here

  7. Diese URL sollte das direkte Herunterladen Ihrer großen Dateien ermöglichen.

[bearbeiten]

Ich habe vergessen hinzuzufügen. Wenn Sie zum Organisieren Ihrer Dateien Unterordner verwenden, verwenden Sie einfach den Ordnernamen, der in einer URL-Hierarchie zu erwarten ist.

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


Was ich wollte

Ich habe ein benutzerdefiniertes Debian-Image mit Virtual Box for Vagrant erstellt. Ich wollte diese ".box" -Datei mit Kollegen teilen, damit sie den direkten Link in ihre Vagrant-Datei einfügen können.

Am Ende brauchte ich einen direkten Link zur eigentlichen Datei.

Google Drive-Problem

Wenn Sie die Dateiberechtigungen so festlegen, dass sie öffentlich verfügbar sind, und einen Direktzugriffslink erstellen/generieren, indem Sie etwas wie gdocs2direct verwenden oder den Link einfach selbst erstellen:

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

Sie erhalten einen Cookie-basierten Bestätigungscode und die Aufforderung "Google konnte diese Datei nicht scannen". Diese Aufforderung funktioniert nicht für Dinge wie wget oder Vagrantfile configs.

Der Code, den es generiert, ist ein einfacher Code, der die GET-Abfragevariable ...&confirm=### An die Zeichenfolge anfügt, jedoch benutzerspezifisch ist, sodass Sie diese Abfragevariable nicht für andere kopieren/einfügen können.

Wenn Sie jedoch die oben beschriebene Methode zum Hosten von Webseiten verwenden, können Sie diese Eingabeaufforderung umgehen.

Ich hoffe das hilft!

62
jmbertucci

Wenn Sie auf die Seite "Diese Datei kann nicht auf Viren überprüft werden" intermezzo stoßen, ist der Download nicht so einfach.

Sie müssen im Wesentlichen zuerst den normalen Download-Link herunterladen, der Sie jedoch auf die Seite "Trotzdem herunterladen" weiterleitet. Sie müssen Cookies von dieser ersten Anfrage speichern, den Link ermitteln, auf den die Schaltfläche "Trotzdem herunterladen" verweist, und dann diesen Link zum Herunterladen der Datei verwenden, aber die Cookies wiederverwenden, die Sie von der ersten Anfrage erhalten haben.

Hier ist eine Bash-Variante des Download-Vorgangs mit CURL:

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

Anmerkungen:

  • dieser Vorgang wird wahrscheinlich nach einigen Google-Änderungen nicht mehr funktionieren
  • der Befehl grep verwendet die Perl-Syntax (-P) und den Operator \K, was im Wesentlichen bedeutet, dass "nichts enthalten ist, das \K vor dem übereinstimmenden Ergebnis steht. Ich weiß nicht In welcher Version von grep wurden diese Optionen eingeführt? In älteren oder nicht-Ubuntu-Versionen ist dies wahrscheinlich nicht der Fall
  • eine Java -Lösung wäre mehr oder weniger dieselbe, nimm einfach eine HTTPS-Bibliothek, die Cookies verarbeiten kann, und eine nette Textanalyse-Bibliothek
35
Martin Pecka

Ich weiß, dass dies eine alte Frage ist, aber ich konnte nach einigen Nachforschungen keine Lösung für dieses Problem finden, also teile ich mit, was für mich funktioniert hat.

Ich habe diesen C # -Code für eines meiner Projekte geschrieben. Die Warnung vor dem Scan-Virus kann programmgesteuert umgangen werden. Der Code kann wahrscheinlich nach Java konvertiert werden.

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;
    }
}

Dies scheint ab dem 19. Mai 2015 erneut aktualisiert zu werden:

So habe ich es geschafft:

Machen Sie Ihren Ordner wie in der kürzlich aktualisierten Antwort von jmbertucci für alle öffentlich. Dies ist etwas komplizierter als zuvor. Sie müssen auf Erweitert klicken, um den Ordner in "On - Public on the web" zu ändern.

Suchen Sie die UUID Ihres Ordners wie zuvor - gehen Sie einfach in den Ordner und suchen Sie Ihre UUID in der Adressleiste:

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

Dann gehe zu

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

Es leitet Sie zu einer Indexseite mit einer riesigen Unterdomäne weiter, aber Sie sollten in der Lage sein, die Dateien in Ihrem Ordner zu sehen. Dann können Sie mit der rechten Maustaste klicken, um den Link zu der gewünschten Datei zu speichern (mir ist aufgefallen, dass dieser direkte Link auch diese große Unterdomäne für googledrive.com Enthält). Arbeitete großartig für mich mit wget.

Dies scheint auch mit den freigegebenen Ordnern anderer zu funktionieren.

z.B.,

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

karten zu

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

Mit einem Rechtsklick kann ein direkter Link zu einer dieser Dateien gespeichert werden.

3
Sean

# Fall 1: Laden Sie eine Datei mit geringer Größe herunter.

# Fall 2: Datei mit großer Größe herunterladen.

  • Sie haben eine Seite einer zurückgegebenen Viren-Scan-Warnmeldung angeklebt. Beim Parsen des HTML-Dom-Elements habe ich versucht, einen Link mit dem Bestätigungscode unter der Schaltfläche "Trotzdem herunterladen" zu erhalten, aber es hat nicht funktioniert. Möglicherweise sind Cookies oder Sitzungsinformationen erforderlich. Bildbeschreibung hier eingeben

LÖSUNG:

  • Schließlich fand ich eine Lösung für zwei der oben genannten Fälle. Sie müssen nur httpConnection.setDoOutput(true) in den Verbindungsschritt setzen, um einen Json zu erhalten.

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

Anschließend können Sie einen beliebigen Json-Parser zum Lesen von downloadUrl, fileName und sizeBytes verwenden.

  • Sie können folgen Schnipsel verweisen, hoffe es hilft.

    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;
    }
    

Und

   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

Ich habe dieses Befehlszeilentool verwendet, um Dateien von Google Drive herunterzuladen. Folgen Sie einfach den Anweisungen im Abschnitt Erste Schritte und laden Sie die Dateien in wenigen Minuten von Google Drive herunter.

1
ibrahim

Die Verwendung eines Dienstkontos funktioniert möglicherweise für Sie.

1
pinoyyid

Ich würde in Betracht ziehen, über den Link herunterzuladen, die Seite, auf der Sie den Bestätigungslink finden, zu scrappen und diese dann herunterzuladen.

Wenn Sie sich die URL "Trotzdem herunterladen" ansehen, gibt es einen zusätzlichen Abfrageparameter confirm mit einem scheinbar zufällig generierten Token. Da es zufällig ist ... und Sie wahrscheinlich nicht herausfinden möchten, wie Sie es selbst generieren, ist Scraping möglicherweise der einfachste Weg, ohne etwas über die Funktionsweise der Site zu wissen.

Möglicherweise müssen Sie verschiedene Szenarien berücksichtigen.

0

Wenn Sie lediglich programmgesteuert (im Gegensatz dazu, dem Benutzer einen Link zum Öffnen in einem Browser zu geben) eine Datei über die Google Drive-API herunterladen möchten, empfehle ich die Verwendung des downloadUrl der Datei anstelle des webContentLink, wie hier dokumentiert: https://developers.google.com/drive/web/manage-downloads

0
David