在 C# 中使用 WebClient 下载大型 Google 驱动器文件
Downloading Large Google Drive files with WebClient in C#
我知道已经有很多关于这个主题的问题了。看完所有帖子后,我决定在确认 HTML 页面中获得重定向 URL,然后将其用作直接 link 下载。
众所周知,直接下载link的原始URL格式是这样的
https://drive.google.com/uc?export=download&id=XXXXX..
但是如果目标文件的大小很大,那么就是这样。
https://drive.google.com/uc?export=download&confirm=RRRR&id=XXXXX..
我从第一次下载的数据中可以得到RRRR,所以我需要尝试两次才能下载真正的文件。这个概念非常简单,但我无法让它发挥作用。
class Test
{
class MyWebClient: WebClient
{
CookieContainer c = new CookieContainer();
protected override WebRequest GetWebRequest(Uri u)
{
var r = (HttpWebRequest) base.GetWebRequest(u);
r.CookieContainer = c;
return r;
}
}
static string GetRealURL(string filename)
{
// Some Jobs to Parse....
return directLink;
}
static void Main()
{
MyWebClient wc = new MyWebClient();
string targetLink = "https://drive.google.com/uc?export=download&id=XXXXXXX";
wc.DownloadFile(targetLink, "tempFile.tmp");
targetLink = GetRealURL("tempFile.tmp");
wc.DownloadFile(targetLink, "realFile.dat");
}
}
我做错了什么?
我可以从第一个文件获得正确的下载 link,但我在第二次尝试时得到了另一个带有另一个确认代码的确认页面文件。我以为这是因为 cookie,所以我创建了自己的 WebClient
class,正如您在上面看到的那样。
另外我原来用的是DownloadFileAsync()
,为了以防万一改成了DownloadFile()
,结果还是一样。。
我仍然认为它与饼干有关。
我在这里错过了什么?
我遇到了同样的问题,但已经在 HttpClient 中解决了。我尝试通过您使用 WebClient 的方法并使其正常工作。您没有显示您的 GetRealUrl()
来源,但我敢打赌,问题就出在这里。这是我的做法:
- 您需要解析 html 响应以获取“仍然下载”按钮的 href 属性中的 url。它只会有相对的url,(
/uc?export=download...
部分)
- 您需要将 xml 转义字符
&
替换为 &
- 然后您可以使用域
https://drive.google.com
构建 url
此时您可以下载文件。这是源代码(用于测试 WPF 应用程序):
class MyWebClient : WebClient
{
CookieContainer c = new CookieContainer();
protected override WebRequest GetWebRequest(Uri u)
{
var r = (HttpWebRequest)base.GetWebRequest(u);
r.CookieContainer = c;
return r;
}
}
private async void WebClientTestButtonGdrive_Click(object sender, RoutedEventArgs e)
{
using (MyWebClient client = new MyWebClient())
{
//get the warning page
string htmlPage = await client.DownloadStringTaskAsync("https://drive.google.com/uc?id=XXXXXXX&export=download");
//use HtmlAgilityPack to get the url with the confirm parameter in the url
HtmlDocument document = new HtmlDocument();
document.LoadHtml(htmlPage);
HtmlNode node = document.DocumentNode;
HtmlNode urlNode = node.SelectSingleNode(@"//a[contains(@href, 'XXXXXXX') and contains(@id, 'uc-download-link')]//@href");
string downloadUrl = urlNode.Attributes["href"].Value;
downloadUrl = downloadUrl.Replace("&", "&");
downloadUrl = "https://drive.google.com" + downloadUrl;
//download the file
if (File.Exists("FileToDownload.zip"))
File.Delete("FileToDownload.zip");
await client.DownloadFileTaskAsync(downloadUrl, "FileToDownload.zip");
}
}
我知道已经有很多关于这个主题的问题了。看完所有帖子后,我决定在确认 HTML 页面中获得重定向 URL,然后将其用作直接 link 下载。
众所周知,直接下载link的原始URL格式是这样的
https://drive.google.com/uc?export=download&id=XXXXX..
但是如果目标文件的大小很大,那么就是这样。
https://drive.google.com/uc?export=download&confirm=RRRR&id=XXXXX..
我从第一次下载的数据中可以得到RRRR,所以我需要尝试两次才能下载真正的文件。这个概念非常简单,但我无法让它发挥作用。
class Test
{
class MyWebClient: WebClient
{
CookieContainer c = new CookieContainer();
protected override WebRequest GetWebRequest(Uri u)
{
var r = (HttpWebRequest) base.GetWebRequest(u);
r.CookieContainer = c;
return r;
}
}
static string GetRealURL(string filename)
{
// Some Jobs to Parse....
return directLink;
}
static void Main()
{
MyWebClient wc = new MyWebClient();
string targetLink = "https://drive.google.com/uc?export=download&id=XXXXXXX";
wc.DownloadFile(targetLink, "tempFile.tmp");
targetLink = GetRealURL("tempFile.tmp");
wc.DownloadFile(targetLink, "realFile.dat");
}
}
我做错了什么?
我可以从第一个文件获得正确的下载 link,但我在第二次尝试时得到了另一个带有另一个确认代码的确认页面文件。我以为这是因为 cookie,所以我创建了自己的 WebClient
class,正如您在上面看到的那样。
另外我原来用的是DownloadFileAsync()
,为了以防万一改成了DownloadFile()
,结果还是一样。。
我仍然认为它与饼干有关。
我在这里错过了什么?
我遇到了同样的问题,但已经在 HttpClient 中解决了。我尝试通过您使用 WebClient 的方法并使其正常工作。您没有显示您的 GetRealUrl()
来源,但我敢打赌,问题就出在这里。这是我的做法:
- 您需要解析 html 响应以获取“仍然下载”按钮的 href 属性中的 url。它只会有相对的url,(
/uc?export=download...
部分) - 您需要将 xml 转义字符
&
替换为&
- 然后您可以使用域
https://drive.google.com
构建 url
此时您可以下载文件。这是源代码(用于测试 WPF 应用程序):
class MyWebClient : WebClient
{
CookieContainer c = new CookieContainer();
protected override WebRequest GetWebRequest(Uri u)
{
var r = (HttpWebRequest)base.GetWebRequest(u);
r.CookieContainer = c;
return r;
}
}
private async void WebClientTestButtonGdrive_Click(object sender, RoutedEventArgs e)
{
using (MyWebClient client = new MyWebClient())
{
//get the warning page
string htmlPage = await client.DownloadStringTaskAsync("https://drive.google.com/uc?id=XXXXXXX&export=download");
//use HtmlAgilityPack to get the url with the confirm parameter in the url
HtmlDocument document = new HtmlDocument();
document.LoadHtml(htmlPage);
HtmlNode node = document.DocumentNode;
HtmlNode urlNode = node.SelectSingleNode(@"//a[contains(@href, 'XXXXXXX') and contains(@id, 'uc-download-link')]//@href");
string downloadUrl = urlNode.Attributes["href"].Value;
downloadUrl = downloadUrl.Replace("&", "&");
downloadUrl = "https://drive.google.com" + downloadUrl;
//download the file
if (File.Exists("FileToDownload.zip"))
File.Delete("FileToDownload.zip");
await client.DownloadFileTaskAsync(downloadUrl, "FileToDownload.zip");
}
}