使用Google Drive API从Google云端硬盘直接下载

时间:2013-12-18 18:39:21

标签: java google-drive-api

我用java编写的桌面应用程序尝试从Google云端硬盘下载公共文件。正如我发现的那样,它可以通过使用文件webContentLink来实现(它可以在没有用户授权的情况下下载公共文件)。

因此,下面的代码适用于小文件:

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

但它不适用于大文件,因为在这种情况下,如果没有用户确认谷歌病毒扫描警告,则无法通过webContentLink直接下载文件。请参阅示例:web content link

所以我的问题是如何在未经用户授权的情况下从Google云端硬盘获取公开文件的内容?

15 个答案:

答案 0 :(得分:62)

2015年12月8日更新 根据{{​​3}}使用

googledrive.com/host/ID

方法将于2016年8月31日关闭。


我刚遇到这个问题。

技巧是将您的Google云端硬盘文件夹视为网络托管服务商。

2015年4月1日更新

Google云端硬盘已更改,并且有一种简单的方法可以直接链接到您的硬盘。我将以前的答案留在下面作为参考,但这里是一个更新的答案。

  1. 在Google云端硬盘中创建公用文件夹。

  2. 公开分享此动态。

    enter image description here

  3. 当您在该文件夹中时,从地址栏中获取您的文件夹UUID

    enter image description here
  4. 将该UUID放入此URL中

    https://googledrive.com/host/<folder UUID>/
  5. 将文件名添加到文件所在的位置。

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

  6. Google Support
    Which is intended functionality by Google

    您只需获取公共共享驱动器文件夹的主机 URL即可。为此,您可以在Google云端硬盘中上传纯HTML文件并预览以查找您的主机网址。

    以下是步骤:

    1. 在Google云端硬盘中创建一个文件夹。

    2. 公开分享此动态。

      enter image description here

    3. 上传简单的HTML文件。添加任何其他文件(子文件夹ok)

      enter image description here

    4. 在Google云端硬盘中打开并“预览”HTML文件

      enter image description here

    5. 获取此文件夹的URL地址

      enter image description here

    6. 从您的网址文件夹库中创建直接链接网址

      enter image description here

    7. 此网址应允许直接下载您的大文件。

    8. [编辑]

      我忘了添加。如果使用子文件夹来组织文件,则可以像在URL层次结构中一样使用文件夹名称。

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


      我想做什么

      我使用Virtual Box for Vagrant创建了一个自定义Debian映像。我想与同事分享这个“.box”文件,这样他们就可以将直接链接放到他们的Vagrant文​​件中。

      最后,我需要直接链接到实际文件。

      Google云端硬盘问题

      如果您将文件权限设置为公开可用,并使用new Google Drive Link工具之类的内容创建/生成直接访问链接,或者只是自己制作链接:

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

      您将收到基于Cookie的验证码并提示“Google无法扫描此文件”提示,这对 wget 或Vagrantfile配置等内容无效。

      它生成的代码是一个简单的代码,它将GET查询变量...&confirm=###附加到字符串中,但它是按用户特定的,所以它不像你可以为其他人复制/粘贴该查询变量。

      但是如果你使用上面的“网页托管”方法,你可以绕过那个提示。

      我希望有所帮助!

答案 1 :(得分:33)

如果你面对“此文件无法检查病毒” intermezzo页面,下载并不那么容易。

您基本上需要先下载正常的下载链接,然后将其重定向到“仍然下载”页面。您需要存储第一个请求中的cookie,找到“依次下载”按钮指向的链接,然后使用此链接下载文件,但重用第一个请求中获得的cookie。

以下是使用CURL的下载过程的bash变体:

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

注意:

  • 此过程可能会在Google更改后停止工作
  • grep命令使用Perl语法(-P)和\K“运算符”,这实际上意味着“不包括匹配结果前\K之前的任何内容。我不知道哪个版本的grep引入了这些选项,但古代或非Ubuntu版本可能没有它
  • Java解决方案或多或少相同,只需要一个可以处理cookie的HTTPS库,以及一些不错的文本解析库

答案 2 :(得分:4)

我知道这是一个老问题,但经过一些研究后我找不到解决这个问题的方法,所以我分享了对我有用的东西。

我已经为我的一个项目编写了这个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( "&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;
    }
}

答案 3 :(得分:3)

自2015年5月19日起,这似乎再次更新:

我是如何开始工作的:

与jmbertucci最近更新的答案一样,将您的文件夹公开给所有人。这比以前复杂一点,您必须单击“高级”将文件夹更改为“开启 - 在Web上公开”。

像以前一样找到您的文件夹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

右键单击可以保存指向这些文件的直接链接。

答案 4 :(得分:2)

#Case 1:下载小尺寸的文件。

#Case 2:下载大尺寸文件。

  • 您在墙上留下了一张返回的病毒扫描警报页面。通过解析html dom元素,我试图在“仍然下载”按钮下获得确认代码的链接,但它不起作用。它可能需要cookie或会话信息。 enter image description here

SOLUTION:

  • 最后,我找到了上述两个案例的解决方案。只需将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;

    }

答案 5 :(得分:1)

使用服务帐户可能对您有用。

答案 6 :(得分:1)

https://github.com/google/skicka

我使用此命令行工具从Google云端硬盘下载文件。只需按照“入门”部分中的说明操作,您就可以在几分钟内从Google云端硬盘下载文件。

答案 7 :(得分:1)

检查一下:

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

答案 8 :(得分:1)

截至2020年8月的更新:

这是最近为我工作的-

上传文件并获得任何人都可以看到的共享链接(在共享链接选项中将权限从“受限”更改为“有链接的任何人”)

然后运行:

 SHAREABLE_LINK=<google drive shareable link>
 curl -L https://drive.google.com/uc\?id\=$(echo $SHAREABLE_LINK | cut -f6 -d"/")

答案 9 :(得分:0)

我会考虑从链接下载,抓取您获取确认链接的页面,然后下载。

如果您查看“无论如何下载”URL,它会有一个额外的confirm查询参数,其中包含一个看似随机生成的令牌。由于它是随机的......你可能不想弄清楚如何自己生成它,因此在不了解网站运作方式的情况下,抓取可能是最简单的方法。

您可能需要考虑各种情况。

答案 10 :(得分:0)

如果您只是想以编程方式(与向用户提供在浏览器中打开的链接相反)通过Google Drive API下载文件,我建议您使用文件的downloadUrl而不是{ {1}},如此处所述:https://developers.google.com/drive/web/manage-downloads

答案 11 :(得分:0)

我在直接下载时遇到了问题,因为我使用多个Google帐户登录。 解决方案是附加authUser=0参数。要下载的示例请求网址:https://drive.google.com/uc?id=FILEID&authuser=0&export=download

答案 12 :(得分:0)

对于任何共享链接,替换 FILENAME 和 FILEID,(对于需要确认的非常大的文件):

wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt - -keep-session-cookies --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 文件名 && rm -rf /tmp/cookies.txt

(对于小文件): wget --no-check-certificate 'https://docs.google.com/uc?export=download&id=FILEID' -O 文件名

答案 13 :(得分:-1)

https://drive.google.com/uc?export=download&id=FILE_ID用文件ID替换FILE_ID。

如果你不知道是文件ID,请查看这篇文章Article LINK

答案 14 :(得分:-1)

我只是创建一个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源代码并在java中下载。