Descarga directa de Google Drive con la API de Google Drive

Mi aplicación de escritorio, escrita en java, intenta descargar archivos públicos de Google Drive. Como descubrí, puede implementarse utilizando el archivo webContentLink (es para la capacidad de descargar archivos públicos sin la autorización del usuario).

Entonces, el siguiente código funciona con archivos pequeños:

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

Pero no funciona en archivos grandes, porque en este caso el archivo no se puede descargar directamente a través de webContentLink sin la confirmación del usuario con la advertencia de escaneo de virus de google. Ver un ejemplo: enlace de contenido web .

¿Entonces mi pregunta es cómo obtener el contenido de un archivo público de Google Drive sin la autorización del usuario?

Actualice el 8 de diciembre de 2015 De acuerdo con el Soporte de Google que usa el

 googledrive.com/host/ID 

el método se apagará el 31 de agosto de 2016.


Me encontré con este problema.

El truco es tratar su carpeta de Google Drive como un host web.

Actualización 1 de abril de 2015

Google Drive ha cambiado y hay una manera simple de vincularlo directamente a su unidad. Dejé mis respuestas anteriores a continuación para referencia, pero aquí hay una respuesta actualizada.

  1. Crea una carpeta pública en Google Drive.
  2. Comparte esta unidad públicamente.

    enter image description here

  3. Obtenga su UUID de carpeta de la barra de direcciones cuando se encuentre en esa carpeta

    enter image description here

  4. Pon ese UUID en esta URL

    https://googledrive.com/host//

  5. Agregue el nombre del archivo a donde se encuentra su archivo.

    https://googledrive.com/host//


Cuál es la funcionalidad prevista por Google
nuevo enlace de Google Drive .

Todo lo que tiene que hacer es simple obtener la URL del host para una carpeta de disco compartida públicamente. Para hacer esto, puede cargar un archivo HTML sin formato y obtener una vista previa en Google Drive para encontrar su URL de host.

Estos son los pasos:

  1. Crea una carpeta en Google Drive.
  2. Comparte esta unidad públicamente.

    enter image description here

  3. Cargue un archivo HTML simple. Agregue cualquier archivo adicional (las subcarpetas están bien)

    enter image description here

  4. Abra y “vista previa” del archivo HTML en Google Drive

    enter image description here

  5. Obtener la dirección URL para esta carpeta

    enter image description here

  6. Crea una URL de enlace directo desde tu base de carpetas URL

    enter image description here

  7. Esta URL debe permitir descargas directas de sus archivos de gran tamaño.

[editar]

Olvidé agregar Si usa subcarpetas para organizar sus archivos, simplemente use el nombre de la carpeta como se esperaría en una jerarquía de URL.

https://googledrive.com/host//images/my-image.png


Lo que estaba buscando hacer

Creé una imagen Debian personalizada con Virtual Box for Vagrant. Quería compartir este archivo “.box” con colegas para que pudieran poner el enlace directo en su Vagrantfile.

Al final, necesitaba un enlace directo al archivo real.

Problema de Google Drive

Si configura los permisos del archivo para que estén disponibles públicamente y cree / genere un enlace de acceso directo utilizando algo como la herramienta gdocs2direct o simplemente creando el enlace usted mismo:

https://docs.google.com/uc?export=download&id=

Obtendrá un código de verificación basado en cookies y le pedirá que le solicite “Google no puede escanear este archivo”, lo que no funcionará para cosas como las configuraciones de wget o Vagrantfile.

El código que genera es un código simple que agrega la variable de consulta GET ...&confirm=### a la cadena, pero es por cada usuario específico, por lo que no es posible copiar / pegar esa variable de consulta para otros.

Pero si usa el método anterior de “alojamiento de páginas web”, puede solucionar ese problema.

¡Espero que eso ayude!

Si te enfrentas a la página intermezzo “Este archivo no se puede verificar para detectar virus” , la descarga no es tan fácil.

Básicamente, es necesario descargar primero el enlace de descarga normal, que sin embargo lo redirecciona a la página “Descargar de todos modos”. Debe almacenar las cookies de esta primera solicitud, encontrar el enlace al que apunta el botón “Descargar de todos modos” y luego usar este enlace para descargar el archivo, pero reutilizando las cookies que recibió de la primera solicitud.

Aquí hay una variante bash del proceso de descarga usando 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/\&/\&/g')" > FINAL_DOWNLOADED_FILENAME 

Notas:

  • este procedimiento probablemente dejará de funcionar después de algunos cambios en Google
  • el comando grep usa la syntax de Perl ( -P ) y el “operador \K ” que significa esencialmente “no incluir nada que preceda \K al resultado coincidente. No sé qué versión de grep presentó estas opciones, pero antigua o no -Las versiones de Ubuntu probablemente no lo tengan
  • una solución Java sería más o menos la misma, solo tome una biblioteca HTTPS que pueda manejar las cookies, y una buena biblioteca de análisis de texto

Esto parece estar actualizado nuevamente a partir del 19 de mayo de 2015:

Cómo lo hice funcionar:

Como en la respuesta recientemente actualizada de jmbertucci, haz que tu carpeta sea pública para todos. Esto es un poco más complicado que antes, debe hacer clic en Avanzado para cambiar la carpeta a “Encendido – Público en la web”.

Encuentra tu carpeta UUID como antes – solo ve a la carpeta y encuentra tu UUID en la barra de direcciones:

 https://drive.google.com/drive/folders/ 

Luego dirígete a

 https://googledrive.com/host/ 

Te redirigirá a una página de tipo índice con un subdominio gigante, pero deberías poder ver los archivos en tu carpeta. Luego puede hacer clic derecho para guardar el enlace al archivo que desea (me di cuenta de que este enlace directo también tiene este gran subdominio para googledrive.com ). Funcionó muy bien para mí con wget .

Esto también parece funcionar con las carpetas compartidas de los demás.

p.ej,

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

mapas para

https://googledrive.com/host/0B7l10Bj_LprhQnpSRkpGMGV2eE0

Y un clic derecho puede guardar un enlace directo a cualquiera de esos archivos.

Sé que esta es una vieja pregunta, pero no pude encontrar una solución a este problema después de algunas investigaciones, así que estoy compartiendo lo que funcionó para mí.

He escrito este código de C # para uno de mis proyectos. Puede omitir la advertencia de virus de exploración programáticamente. El código probablemente se puede convertir a 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 , 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( "" ) ) ) 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( "&", "&" ); } 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 _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(); } } 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; } } 

Usar una cuenta de servicio podría funcionar para usted.

# Caja 1: descarga el archivo con un tamaño pequeño.

# Caja 2: descarga el archivo con un tamaño grande.

  • Pegaste una pared de una página de alerta de escaneo de virus devuelta. Al analizar el elemento html dom, traté de obtener un enlace con el código de confirmación en el botón “Descargar de todos modos”, pero no funcionó. Es posible que se requiera una cookie o información de sesión. enter image description here

SOLUCIÓN:

  • Finalmente encontré la solución para dos casos anteriores. Solo necesita poner httpConnection.setDoOutput(true) en el paso de conexión para obtener un Json.

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

Luego, puede usar cualquier analizador Json para leer downloadUrl, fileName y sizeBytes.

  • Puedes referirme al fragmento de seguimiento, espero que ayude.

     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> map = httpConnection.getHeaderFields(); List 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; } 

Y

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

Consideraría descargar desde el enlace, raspando la página que tienes para agarrar el enlace de confirmación, y luego descargarlo.

Si observas la URL “descargar de todos modos”, tiene un parámetro de consulta de confirm adicional con un token aparentemente generado aleatoriamente. Dado que es aleatorio … y probablemente no quiera descubrir cómo generarlo usted mismo, raspar podría ser la forma más fácil sin saber nada sobre cómo funciona el sitio.

Es posible que deba considerar varios escenarios.

Si solo desea progtwigr (como oposición a darle al usuario un enlace para abrir en un navegador) descargar un archivo a través de la API de Google Drive, le sugiero que use la downloadUrl del archivo en lugar de la webContentLink , como se documenta aquí: https: //developers.google.com/drive/web/manage-downloads

https://github.com/google/skicka

Utilicé esta herramienta de línea de comandos para descargar archivos de Google Drive. Solo siga las instrucciones en la sección de Introducción y descargue los archivos de Google Drive en minutos.

https://drive.google.com/uc?export=download&id=FILE_ID reemplace el FILE_ID con el ID del archivo.

si no sabe si el archivo es id, entonces consulte este artículo Artículo ENLACE

Simplemente creo un javascript para que capture automáticamente el enlace y descargue y cierre la pestaña con la ayuda de tampermonkey .

 // ==UserScript== // @name Bypass Google drive virus scan // @namespace SmartManoj // @version 0.1 // @description Quickly get the download link // @author SmartManoj // @match https://drive.google.com/uc?id=*&export=download* // @grant none // ==/UserScript== function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function demo() { await sleep(5000); window.close(); } (function() { location.replace(document.getElementById("uc-download-link").href); demo(); })(); 

Del mismo modo, puede obtener la fuente html de la url y descargarla en java.