在C#中使用哪个HTTP客户端通过进度跟踪获取,发布和下载文件?

时间:2018-12-30 21:11:20

标签: c# http

我的目标是:

  • 通过会话访问网站。
  • 使用HtmlAgilityPack传递登录信息。
  • 从该会话中访问多个文件(没有特定顺序,但这没关系)。
  • 下载这些文件,同时跟踪下载进度。
  • 能够在下载之前获取文件名(我发现可以使用标题中的content-disposition)。

  • 我尝试了HttpClient和RestSharp,但都不允许跟踪下载进度或在下载之前访问文件名。
  • 我尝试了WebClient,它解决了之前的两个问题,但不允许在此处获取或发布强制性的典型方法。

我期望的是能够在登录后解析网站并扫描html文件以下载文件(我知道该怎么做,并且已经解决了),同时可以扫描以某种方式检索文件名像将来的对象一样(我想这将使用异步任务解决,如果立即请求,则可以等待,否则可以在后台调用),然后在请求文件时,应在显示进度的同时下载文件。

1 个答案:

答案 0 :(得分:1)

和往常一样,我花了数小时来寻找解决方案,当我在此处发布问题时,我便将其找出来。

事实证明,HttpClient足以满足多个用户的需求,当SO回答“不可能”时,我只需要更深入地研究而不停止阅读,这意味着特定文件不支持,但总体可能。无论如何,这就是我所需要的:

var processMsgHander = new ProgressMessageHandler(new HttpClientHandler());
processMsgHander.HttpSendProgress += (sender, e) =>
    {
        //add your codes base on e.BytesTransferred and e.ProgressPercentage
    };

processMsgHander.HttpReceiveProgress += (sender, e) =>
    {
        e.BytesTransferred.Dump();
        //add your codes base on e.BytesTransferred and e.ProgressPercentage
    };

var client = new HttpClient(processMsgHander);
client.BaseAddress = new Uri("http://mypage.com/");

var login = await client.GetAsync("http://mypage.com/login");

var text = await login.Content.ReadAsStringAsync();

var doc = new HtmlDocument();
doc.LoadHtml(text);

var hiddenInput = doc.DocumentNode.SelectNodes("//form//input[@type=\"hidden\"]");

var loginData = new Dictionary<string, string>();

foreach (var x in hiddenInput)
{
    loginData[x.Attributes.First(t => t.Name == "name").Value] = x.Attributes.First(t => t.Name == "value").Value;
}

loginData["username"] = "MyUsername";
loginData["password"] = "MyPasswordShouldntBeHere";

var lginData = new FormUrlEncodedContent(loginData.ToArray());
var response = await client.PostAsync(login.RequestMessage.RequestUri, lginData);

var tF = DateTime.Now;

var file = await client.GetAsync("http://mypage.com/file");

var headers = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, "http://mypage.com/file"));

var tE = DateTime.Now;

file.Content.Headers.ElementAt(1).Dump(); // if only this is called then the file is downloaded
headers.Content.Headers.ElementAt(1).Dump(); // if only this is called then the file is not downloaded
// in my use case either the first line of the second will be called at one case
// (accordingly the var file and var headers won't both be called)

(tE - tF).Dump();