Прямая загрузка с Google Drive с использованием Google Drive API
Мое настольное приложение, написанное на Java, пытается загрузить общедоступные файлы с Google Drive. Как я выяснил, это может быть реализовано с помощью файла webContentLink
(это для возможности загрузки публичных файлов без авторизации пользователя).
Итак, приведенный ниже код работает с небольшими файлами:
String webContentLink = aFile.getWebContentLink();
InputStream in = new URL(webContentLink).openStream();
Но это не работает с большими файлами, потому что в этом случае файл не может быть загружен напрямую через webContentLink
без подтверждения пользователя с предупреждением о сканировании вирусов Google. Смотрите пример: ссылка на веб-контент.
Итак, мой вопрос: как получить содержимое общедоступного файла с Google Диска без авторизации пользователя?
15 ответов
Обновление от 8 декабря 2015 г. Согласно службе поддержки Google, используя
googledrive.com/host/ID
метод будет отключен 31 августа 2016 года.
Я только столкнулся с этой проблемой.
Хитрость заключается в том, чтобы относиться к вашей папке Google Drive как к веб-хостингу.
Обновление 1 апреля 2015
Диск Google изменился, и появилась простая ссылка на ваш диск. Я оставил свои предыдущие ответы ниже для справки, но вот обновленный ответ.
- Создайте общую папку на Google Диске.
- Поделитесь этим диском публично.
- Получите ваш UUID папки из адресной строки, когда вы находитесь в этой папке
- Поместите этот UUID в этот URL
https://googledrive.com/host/<folder UUID>/
- Добавьте имя файла, где находится ваш файл.
https://googledrive.com/host/<folder UUID>/<file name>
Какая функциональность предназначена для Google
новая ссылка на Google Drive.
Все, что вам нужно сделать, это просто получить URL-адрес хоста для общедоступной папки на диске. Для этого вы можете загрузить простой HTML-файл и просмотреть его на Google Диске, чтобы найти URL своего хоста.
Вот шаги:
- Создайте папку на Google Диске.
- Поделитесь этим диском публично.
- Загрузите простой файл HTML. Добавьте любые дополнительные файлы (подпапки в порядке)
- Открыть и "просмотреть" HTML-файл на Google Диске
- Получить URL-адрес для этой папки
- Создайте URL-адрес прямой ссылки из базы URL-адресов
- Этот URL должен позволять прямую загрузку ваших больших файлов.
[редактировать]
Я забыл добавить. Если вы используете подпапки для организации ваших файлов, вы просто используете имя папки, как и следовало ожидать в иерархии URL.
https://googledrive.com/host/<your public folders id string>/images/my-image.png
Что я хотел сделать
Я создал собственный образ Debian с помощью Virtual Box для Vagrant. Я хотел поделиться этим ".box" файлом с коллегами, чтобы они могли поместить прямую ссылку в свой Vagrantfile.
В конце мне понадобилась прямая ссылка на сам файл.
Проблема с Google Диском
Если вы устанавливаете права доступа к файлам как общедоступные и создаете / генерируете ссылку прямого доступа, используя что-то вроде инструмента gdocs2direct или просто создавая ссылку самостоятельно:
https://docs.google.com/uc?export=download&id=<your file id>
Вы получите проверочный код на основе файлов cookie и запрос "Google не может сканировать этот файл", который не будет работать для таких вещей, как настройки wget или Vagrantfile.
Код, который он генерирует, представляет собой простой код, который добавляет переменную запроса GET ...&confirm=###
в строку, но это зависит от конкретного пользователя, так что вы не можете скопировать / вставить эту переменную запроса для других.
Но если вы используете вышеупомянутый метод "хостинга веб-страниц", вы можете обойти это приглашение.
Надеюсь, это поможет!
Если вы сталкиваетесь со страницей intermezzo "Этот файл нельзя проверить на вирусы", загрузка будет не такой простой.
По сути, вам необходимо сначала скачать обычную ссылку для скачивания, которая, тем не менее, перенаправляет вас на страницу "Все равно скачать". Вам необходимо сохранить куки-файлы из этого первого запроса, найти ссылку, на которую указывает кнопка "Все равно скачать", а затем использовать эту ссылку для загрузки файла, но повторно использовать куки-файлы, полученные вами при первом запросе.
Вот bash-вариант процесса загрузки с использованием 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
Заметки:
- эта процедура, вероятно, перестанет работать после некоторых изменений Google
- команда grep использует синтаксис Perl (
-P
) и\K
"оператор", что по существу означает "не включает ничего предшествующего\K
к согласованному результату. Я не знаю, какая версия grep представила эти опции, но древние или не-Ubuntu версии, вероятно, не имеют ее - Java-решение будет более или менее одинаковым, просто возьмите библиотеку HTTPS, которая может обрабатывать куки, и некоторую хорошую библиотеку для разбора текста
Я знаю, что это старый вопрос, но я не смог найти решение этой проблемы после некоторых исследований, поэтому я делюсь тем, что сработало для меня.
Я написал этот код C# для одного из моих проектов. Это может обойти предупреждение сканирования вируса программно. Код, вероятно, может быть преобразован в 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;
}
}
# Случай 1: скачать файл небольшого размера.
- Вы можете использовать URL-адрес в формате https://drive.google.com/uc?export=download&id=FILE_ID после чего можно напрямую получить входной поток файла.
# Случай 2: скачать файл большого размера.
- Вы застряли на стене страницы предупреждения о вирусной проверке. Разобрав элемент html dom, я попытался получить ссылку с кодом подтверждения под кнопкой "Скачать", но это не сработало. Может потребоваться файл cookie или информация о сеансе. введите описание изображения здесь
РЕШЕНИЕ:
Наконец я нашел решение для двух вышеупомянутых случаев. Просто нужно поставить
httpConnection.setDoOutput(true)
на этапе подключения, чтобы получить Json.)]}' { "disposition":"SCAN_CLEAN", "downloadUrl":"http:www...", "fileName":"exam_list_json.txt", "scanResult":"OK", "sizeBytes":2392}
Затем вы можете использовать любой анализатор Json для чтения downloadUrl, fileName и sizeBytes.
Вы можете сослаться на фрагмент, надеюсь, это поможет.
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; }
А также
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;
}
Похоже, что это будет обновлено с 19 мая 2015 года:
Как я получил это на работу:
Как и в недавно обновленном ответе jmbertucci, сделайте вашу папку общедоступной для всех. Это немного сложнее, чем раньше, вы должны нажать кнопку "Дополнительно", чтобы изменить папку на "Общедоступно в Интернете".
Найдите UUID вашей папки, как и раньше - просто зайдите в папку и найдите свой UUID в адресной строке:
https://drive.google.com/drive/folders/<folder UUID>
Тогда голова к
https://googledrive.com/host/<folder UUID>
Он перенаправит вас на страницу типа индекса с гигантским поддоменом, но вы сможете увидеть файлы в вашей папке. Затем вы можете щелкнуть правой кнопкой мыши, чтобы сохранить ссылку на нужный файл (я заметил, что эта прямая ссылка также имеет этот большой поддомен для googledrive.com
). Отлично сработал для меня wget
,
Это также, кажется, работает с другими общими папками.
например,
https://drive.google.com/folderview?id=0B7l10Bj_LprhQnpSRkpGMGV2eE0&usp=sharing
карты для
https://googledrive.com/host/0B7l10Bj_LprhQnpSRkpGMGV2eE0
И щелчок правой кнопкой мыши может сохранить прямую ссылку на любой из этих файлов.
Обновление от августа 2020 г.:
Это то, что у меня сработало недавно -
Загрузите файл и получите ссылку для общего доступа, которую может видеть любой (измените разрешение с "Ограничено" на "Для всех, у кого есть ссылка" в параметрах ссылки для общего доступа)
Затем запустите:
SHAREABLE_LINK=<google drive shareable link>
curl -L https://drive.google.com/uc\?id\=$(echo $SHAREABLE_LINK | cut -f6 -d"/")
Проверь это:
wget https://raw.githubusercontent.com/circulosmeos/gdown.pl/master/gdown.pl
chmod +x gdown.pl
./gdown.pl https://drive.google.com/file/d/FILE_ID/view TARGET_PATH
Для любой общей ссылки замените FILENAME и FILEID (для очень больших файлов, требующих подтверждения):
wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep- файлы cookie сеанса --no-check-certificate 'https://docs.google.com/uc?export=download&id=FILEID' -O- | sed -rn 's /. confirm = ([0-9A-Za-z_]+). / \1\ n / p ')& id = FILEID"-O FILENAME && rm -rf /tmp/cookies.txt
(Для небольших файлов):wget --no-check-certificate 'https://docs.google.com/uc?export=download&id=FILEID' -O FILENAME
Если вы просто хотите программно (в отличие от предоставления пользователю ссылки для открытия в браузере) загрузить файл через Google Drive API, я бы предложил использовать downloadUrl
файла вместо webContentLink
, как описано здесь: https://developers.google.com/drive/web/manage-downloads
https://github.com/google/skicka
Я использовал этот инструмент командной строки для загрузки файлов с Google Drive. Просто следуйте инструкциям в разделе "Начало работы", и вы должны загрузить файлы с Google Диска за считанные минуты.
Я просто создаю javascript, чтобы он автоматически захватывал ссылку, загружал и закрывал вкладку с помощью 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();
})();
Точно так же вы можете получить HTML-источник URL-адреса и скачать в Java.
У меня возникла проблема с прямой загрузкой, потому что я вошел в систему, используя несколько учетных записей Google. Решение добавленоauthUser=0
параметр. Пример URL-адреса запроса для загрузки:https://drive.google.com/uc?id=FILEID&authuser=0&export=download
Я хотел бы рассмотреть возможность загрузки по ссылке, очистки страницы, которую вы получили, чтобы получить ссылку для подтверждения, а затем загрузить ее.
Если вы посмотрите на URL "скачать в любом случае", у него есть дополнительный confirm
параметр запроса с, казалось бы, случайно сгенерированным токеном. Поскольку он случайный... и вы, вероятно, не хотите выяснять, как его сгенерировать самостоятельно, очистка может быть самым простым способом, ничего не зная о том, как работает сайт.
Возможно, вам придется рассмотреть различные сценарии.
https://drive.google.com/uc?export=download&id=FILE_ID замените FILE_ID идентификатором файла.
если вы не знаете, был ли это идентификатор файла, проверьте эту статью