java - name - Descarga directa desde Google Drive utilizando la API de Google Drive
google drive json api (11)
Mi aplicación de escritorio, escrita en java, intenta descargar archivos públicos desde Google Drive. Como descubrí, se puede implementar mediante el uso de webContentLink
del archivo (es para poder 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 detección de virus de Google. Ver un ejemplo: enlace de contenido web .
¿Entonces mi pregunta es cómo obtener contenido de un archivo público de Google Drive sin la autorización del usuario?
Consideraría descargar desde el enlace, raspar la página en la que se obtiene 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. Ya que es aleatorio ... y probablemente no quiera descubrir cómo generarlo, el raspado 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 descargar un archivo a través de la API de Google Drive mediante programación (como se opone a darle al usuario un enlace para que se abra en un navegador), sugeriría usar la downloadUrl
del archivo en lugar de webContentLink
, como se documenta aquí: https://developers.google.com/drive/web/manage-downloads
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, primero necesita descargar el enlace de descarga normal, que sin embargo lo redirige a la página "Descargar de todos modos". Debe almacenar las cookies desde esta primera solicitud, busque el enlace señalado por el botón "Descargar de todos modos" y luego use este enlace para descargar el archivo, pero reutilice 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 sintaxis 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 cookies, y una buena biblioteca de análisis de texto
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.
Usar una cuenta de servicio podría funcionar para usted.
https://drive.google.com/uc?export=download&id=FILE_ID reemplace FILE_ID con el ID del archivo.
Si no sabe cuál es su ID de archivo, consulte este artículo Artículo ENLACE
https://github.com/google/skicka
Utilicé esta herramienta de línea de comandos para descargar archivos de Google Drive. Simplemente siga las instrucciones en la sección de Primeros pasos y debe descargar los archivos de Google Drive en minutos.
Sé que esta es una pregunta antigua 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 C # para uno de mis proyectos. Puede omitir la advertencia de virus de escaneo mediante programación. 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 <!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( "&", "&" );
}
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;
}
}
# Caso 1: descargar el archivo con un tamaño pequeño.
- Puede usar url con el formato https://drive.google.com/uc?export=download&id=FILE_ID y luego se puede obtener directamente la corriente de entrada del archivo.
# Caso 2: descargar el archivo con gran tamaño.
- Pegaste una pared de una página de alerta de escaneo de virus devuelta. Al analizar el elemento dom html, intenté obtener un enlace con el código de confirmación debajo del botón "Descargar de todos modos" pero no funcionó. Es posible que requiera de cookie o información de sesión. enter image description here
SOLUCIÓN:
Finalmente encontré solución para los 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.
Puede referirse a seguir fragmento de código, 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<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; }
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;
}
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 como referencia, pero aquí hay una respuesta actualizada.
- Crea una carpeta pública en Google Drive.
- Comparte este disco públicamente.
- Obtenga su UUID de carpeta de la barra de direcciones cuando se encuentre en esa carpeta
- Pon ese UUID en esta URL
https://googledrive.com/host/<folder UUID>/
- Agregue el nombre del archivo a donde se encuentra su archivo.
https://googledrive.com/host/<folder UUID>/<file name>
Cuál es la funcionalidad prevista por Google
nuevo enlace de Google Drive .
Todo lo que tiene que hacer es obtener la URL del host para una carpeta de disco compartida públicamente. Para hacer esto, puede cargar un archivo HTML plano y previsualizarlo en Google Drive para encontrar su URL de host.
Estos son los pasos:
- Crea una carpeta en Google Drive.
- Comparte esta unidad públicamente.
- Cargue un archivo HTML simple. Agregue cualquier archivo adicional (las subcarpetas están bien)
- Abra y "vista previa" del archivo HTML en Google Drive
- Obtener la dirección URL para esta carpeta
- Crea una URL de enlace directo desde tu base de carpetas URL
- 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/<your public folders id string>/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 de archivo para que estén disponibles al público 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=<your file id>
Recibirá un código de verificación basado en cookie y un mensaje de "Google no pudo escanear este archivo", que no funcionará para cosas como wget o Vagrantfile configs.
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 utiliza el método anterior de "hospedaje de páginas web", puede evitar ese aviso.
¡Espero que eso ayude!
Esto parece ser actualizado nuevamente a partir del 19 de mayo de 2015:
Cómo lo hice funcionar:
Como en la respuesta actualizada recientemente de jmbertucci, haga que su 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/<folder UUID>
Luego dirígete a
https://googledrive.com/host/<folder UUID>
Lo redireccionará a una página de tipo índice con un subdominio gigante, pero debería poder ver los archivos en su carpeta. Luego puede hacer clic derecho para guardar el enlace al archivo que desea (noté 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.