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.
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.
https://googledrive.com/Host/<folder UUID>/
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:
[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!
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/\&/\&/g')" > FINAL_DOWNLOADED_FILENAME
Anmerkungen:
-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 FallIch 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( "&", "&" );
}
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.
# Fall 1: Laden Sie eine Datei mit geringer Größe herunter.
# Fall 2: Datei mit großer Größe herunterladen.
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;
}
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.
Die Verwendung eines Dienstkontos funktioniert möglicherweise für Sie.
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.
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