web-dev-qa-db-fra.com

Téléchargement direct depuis Google Drive à l'aide de l'API Google Drive

Mon application de bureau, écrite en Java, tente de télécharger des fichiers publics à partir de Google Drive. Comme je l'ai découvert, il peut être implémenté en utilisant le fichier webContentLink du fichier (il permet de télécharger des fichiers publics sans autorisation de l'utilisateur).

Donc, le code ci-dessous fonctionne avec de petits fichiers:

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

Mais cela ne fonctionne pas sur les gros fichiers, car dans ce cas, le fichier ne peut pas être téléchargé directement via webContentLink sans confirmation de l'utilisateur avec l'avertissement de Google antivirus. Voir un exemple: lien de contenu Web .

Ma question est donc de savoir comment obtenir le contenu d'un fichier public à partir de Google Drive sans l'autorisation de l'utilisateur.

35
Philip Voronov

Mise à jour du 8 décembre 2015 Selon Assistance Google en utilisant le

googledrive.com/Host/ID

cette méthode sera désactivée le 31 août 2016.


Je viens de rencontrer ce problème.

Le astuce consiste à traiter votre dossier Google Drive comme un hôte Web.

Mise à jour du 1er avril 2015

Google Drive a changé et il existe un moyen simple de créer un lien direct vers votre lecteur. J'ai laissé mes réponses précédentes ci-dessous pour référence, mais voici une réponse mise à jour.

  1. Créez un dossier public dans Google Drive.

  2. Partagez ce lecteur publiquement.

    enter image description here

  3. Obtenez votre UUID de dossier dans la barre d'adresse lorsque vous vous trouvez dans ce dossier.

    enter image description here
  4. Mettez cet UUID dans cette URL

    https://googledrive.com/Host/<folder UUID>/
  5. Ajoutez le nom du fichier à l'emplacement de votre fichier.

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

Quelle est la fonctionnalité prévue par Google
nouveau lien Google Drive .

Il vous suffit simplement d'obtenir l'URL de l'hôte d'un dossier de lecteur partagé publiquement. Pour ce faire, vous pouvez télécharger un fichier HTML simple et l'aperçu dans Google Drive pour rechercher l'URL de votre hôte.

Voici les étapes:

  1. Créez un dossier dans Google Drive.

  2. Partagez ce lecteur publiquement.

    enter image description here

  3. Téléchargez un simple fichier HTML. Ajouter des fichiers supplémentaires (ok des sous-dossiers)

    enter image description here

  4. Ouvrir et "prévisualiser" le fichier HTML dans Google Drive

    enter image description here

  5. Obtenir l'adresse URL de ce dossier

    enter image description here

  6. Créez une URL de lien direct à partir de votre base de dossiers d'URL

    enter image description here

  7. Cette URL devrait permettre le téléchargement direct de vos gros fichiers.

[modifier]

J'ai oublié d'ajouter. Si vous utilisez des sous-dossiers pour organiser vos fichiers, vous utilisez simplement le nom du dossier comme vous le souhaitez dans une hiérarchie d'URL.

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


Ce que je cherchais à faire

J'ai créé une image Debian personnalisée avec Virtual Box for Vagrant. Je voulais partager ce fichier ".box" avec des collègues pour qu'ils puissent mettre le lien direct dans leur fichier Vagrant.

En fin de compte, j'avais besoin d'un lien direct vers le fichier réel.

Problème lié à Google Drive

Si vous définissez les autorisations de fichier pour qu'elles soient accessibles au public et créez/générez un lien d'accès direct en utilisant quelque chose comme l'outil gdocs2direct ou en créant simplement le lien vous-même:

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

Vous obtiendrez un code de vérification basé sur un cookie et l'invite "Google n'a pas pu analyser ce fichier", qui ne fonctionnera pas pour des éléments tels que wget ou Vagrantfile. configs.

Le code qu'il génère est un code simple qui ajoute la variable de requête GET ...&confirm=### à la chaîne, mais elle est spécifique à l'utilisateur. Vous ne pouvez donc pas copier/coller cette variable de requête pour les autres.

Mais si vous utilisez la méthode "d'hébergement de pages Web" ci-dessus, vous pouvez contourner cette invite.

J'espère que ça aide!

62
jmbertucci

Si vous faites face à la page "Les vérifications de ce fichier ne peuvent pas être vérifiées" intermezzo, le téléchargement n’est pas si simple.

Vous devez essentiellement télécharger d’abord le lien de téléchargement normal, qui vous redirige toutefois vers la page "Télécharger quand même". Vous devez stocker des cookies à partir de cette première demande, trouver le lien indiqué par le bouton "Télécharger quand même", puis utiliser ce lien pour télécharger le fichier, mais en réutilisant les cookies que vous avez obtenus de la première demande.

Voici une variante bash du processus de téléchargement utilisant 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

Remarques:

  • cette procédure cessera probablement de fonctionner après quelques modifications de Google
  • la commande grep utilise la syntaxe Perl (-P) et le \K "opérateur" qui signifie essentiellement "ne pas inclure quoi que ce soit qui précède \K au résultat obtenu. Je ne sais pas quelle version de grep a introduit ces options, mais les versions anciennes ou non-Ubuntu ne l'ont probablement pas
  • a Java serait plus ou moins la même chose, il suffit de prendre une bibliothèque HTTPS pouvant gérer les cookies et une certaine bibliothèque d’analyse de texte Nice
35
Martin Pecka

Je sais que c'est une vieille question mais je ne pouvais pas trouver de solution à ce problème après quelques recherches. Je partage donc ce qui a fonctionné pour moi.

J'ai écrit ce code C # pour l'un de mes projets. Il peut contourner l'alerte de virus d'analyse par programmation. Le code peut probablement être converti en 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;
    }
}
5

Cela semble être mis à jour à nouveau à partir du 19 mai 2015:

Comment je l'ai fait pour fonctionner:

Comme dans la réponse récemment mise à jour de jmbertucci, rendez votre dossier public à tout le monde. C'est un peu plus compliqué qu'avant, vous devez cliquer sur Avancé pour changer le dossier en "On - Public sur le Web".

Trouvez votre UUID de dossier comme avant - allez simplement dans le dossier et trouvez votre UUID dans la barre d'adresse:

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

Puis dirigez-vous vers

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

Il vous redirigera vers une page de type index avec un sous-domaine géant, mais vous devriez pouvoir voir les fichiers de votre dossier. Ensuite, vous pouvez cliquer avec le bouton droit de la souris pour enregistrer le lien vers le fichier souhaité (j'ai remarqué que ce lien direct contient également ce gros sous-domaine pour googledrive.com). A bien fonctionné pour moi avec wget.

Cela semble également fonctionner avec les dossiers partagés des autres.

par exemple.,

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

cartes à

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

Et un clic droit peut enregistrer un lien direct vers l'un de ces fichiers.

3
Sean

# Cas 1: téléchargez un fichier de petite taille.

# Cas 2: téléchargez un fichier de grande taille.

  • Vous avez bloqué un mur d'une page d'alerte antivirus renvoyée. En analysant l'élément html dom, j'ai essayé d'obtenir un lien avec le code de confirmation sous le bouton "Télécharger quand même", mais cela n'a pas fonctionné. Son peut nécessiter des cookies ou des informations de session. entrez la description de l'image ici

SOLUTION:

  • Enfin, j'ai trouvé une solution pour deux cas ci-dessus. Il suffit de mettre httpConnection.setDoOutput(true) à l'étape de connexion pour obtenir un Json.

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

Ensuite, vous pouvez utiliser n'importe quel analyseur Json pour lire downloadUrl, FileName et sizeBytes.

  • Vous pouvez vous référer à Snippet, espérez que cela vous aidera.

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

Et

   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

J'ai utilisé cet outil de ligne de commande pour télécharger des fichiers à partir de Google Drive. Suivez simplement les instructions de la section Mise en route et vous devrez télécharger des fichiers à partir de Google Drive en quelques minutes.

1
ibrahim

L'utilisation d'un compte de service peut fonctionner pour vous.

1
pinoyyid

J'envisagerais de télécharger à partir du lien, de gratter la page pour saisir le lien de confirmation, puis de le télécharger.

Si vous regardez l'URL "télécharger quand même", il contient un paramètre de requête supplémentaire confirm avec un jeton apparemment généré aléatoirement. Étant donné que c'est aléatoire ... et que vous ne voulez probablement pas savoir comment le générer vous-même, gratter pourrait être le moyen le plus simple sans rien connaître du fonctionnement du site.

Vous devrez peut-être envisager divers scénarios.

0
That Umbrella Guy

Si vous souhaitez simplement télécharger par programme (par opposition à donner à l'utilisateur un lien à ouvrir dans un navigateur) télécharger un fichier via l'API Google Drive, je vous suggère d'utiliser le downloadUrl du fichier au lieu du webContentLink, comme documenté ici: https://developers.google.com/drive/web/manage-downloads

0
David