【问题标题】:How to download a (huge) text file using HttpWebRequest with credentials?如何使用带有凭据的 HttpWebRequest 下载(巨大的)文本文件?
【发布时间】:2018-07-31 13:25:05
【问题描述】:

我正在尝试自动从某个网站下载文本文件列表。下载一个文本文件的过程是这样的:

  1. 单击文件名会打开一个弹出窗口。
  2. 内容在弹出窗口中 // 它可以作为字符串下载,但它太大而无法使用 StreamWriter 下载,因为我遇到了内存不足的异常。
  3. 右击->另存为。

我想用 HttpWebRequest 下载这个文件。

我的代码如下所示:

string sTmpCookieString = GetGlobalCookies(webBrowser1.Url.AbsoluteUri);
HttpWebRequest fstRequest = (HttpWebRequest)WebRequest.Create(URL);
fstRequest.Method = "GET";
fstRequest.CookieContainer = new System.Net.CookieContainer();
fstRequest.CookieContainer.SetCookies(webBrowser1.Document.Url, sTmpCookieString);
HttpWebResponse fstResponse = (HttpWebResponse)fstRequest.GetResponse();
StreamReader sr = new StreamReader(fstResponse.GetResponseStream());
string sPageData = sr.ReadToEnd();
sr.Close();

string sViewState = ExtractInputHidden(sPageData, "__VIEWSTATE");
string sEventValidation = this.ExtractInputHidden(sPageData, "__EVENTVALIDATION");

string sUrl = URL;
HttpWebRequest hwrRequest = (HttpWebRequest)WebRequest.Create(sUrl);
hwrRequest.Method = "POST";
hwrRequest.CookieContainer = new System.Net.CookieContainer();

string sPostData = "__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=" + sViewState + "&__EVENTVALIDATION=" + sEventValidation + "&Name=test" + "&Button1=Button";

byte[] bByteArray = Encoding.UTF8.GetBytes(sPostData);
hwrRequest.ContentType = "text/plain";
hwrRequest.CookieContainer.SetCookies(webBrowser1.Document.Url, sTmpCookieString);
hwrRequest.ContentLength = bByteArray.Length;

Stream sDataStream = hwrRequest.GetRequestStream();
sDataStream.Write(bByteArray, 0, bByteArray.Length);
sDataStream.Close();
using (WebResponse response = hwrRequest.GetResponse())
{
    using (sDataStream = response.GetResponseStream())
    {
        StreamReader reader = new StreamReader(sDataStream);
        {
            string sResponseFromServer = reader.ReadToEnd();
            FileStream fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write);
            Byte[] info = new System.Text.UTF8Encoding(true).GetBytes(sResponseFromServer);
            fs.Write(info, 0, info.Length);
            fs.Close();
        }
    }
}

..我不断得到 HTML 的样子:

<!DOCTYPE html>
<html>

<head>    

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
<meta content="Microsoft Visual Studio 7.0" name="GENERATOR" />
...

我认为我的问题在某个地方可能对某人来说不清楚。因此,如果有人指出,我会尽力详细解释。

我会提前感谢任何帮助。

【问题讨论】:

    标签: c# winforms download httpwebrequest


    【解决方案1】:

    您正试图一次阅读整个回复:

    string sResponseFromServer = reader.ReadToEnd();
    

    相反,考虑使用类似的东西:

    using (sDataStream = response.GetResponseStream())
    {
        FileStream fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write);
        sDataStream.CopyTo(fs, 10000);
        fs.Close();                            
    }
    

    第二个参数是缓冲区大小,你可以设置为任何合理的值。

    【讨论】:

      【解决方案2】:

      使用异步版本的 WebRequest 下载:WebRequest.GetResponseAsync()

      从您的using (WebResponse response = hwrRequest.GetResponse()) { };开始
      其余的代码基本没问题。

      根据需要调整用于下载/存储文件的缓冲区大小(此处为132072 字节)。不要无缘无故地变小。

      目标文件使用File.Create() 创建,默认为Create New or OverwriteFileShare.None

      using (HttpWebResponse httpResponse = (HttpWebResponse)await httpRequest.GetResponseAsync())
      using (var stream = httpResponse.GetResponseStream()) {
          if (httpResponse.StatusCode == HttpStatusCode.OK) {
              try {
                  int buffersize = 132072;
                  using (FileStream fileStream = File.Create(["YourFileName"], buffersize, FileOptions.Asynchronous))
                  {
                      int read;
                      byte[] buffer = new byte[buffersize];
                      while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0) {
                          await fileStream.WriteAsync(buffer, 0, read);
                      }
                  };
              }
              catch (DirectoryNotFoundException dnfex) {
                  throw;  //Log, store&notify. Your usual handling.
              }
              catch (PathTooLongException ptlex) {
                  throw;  //Same
              }
              catch (IOException ioex) {
                  throw;  //Same
              }
          }
      };
      return ["YourFileName"];
      

      【讨论】:

      • 我在 resObject.ResourceLenght = fileStream.Position;我想知道 resObject 表示什么。
      • 抱歉,有剩菜。你不需要那个。删除它。已编辑。
      • 我仍然得到 html 而不是页面的内容。你有什么想法吗..?
      • 我不知道该网站是如何运作的。但是,查看尝试的帖子,可能会出现问题。您正在尝试填写 WebForm 字段,正确发布 _VIEWSTATE。然后使用纯文本执行 Post。参数应传递UrlEncoded(当参数之一是电子邮件地址时,@ 除外)。当身份验证失败时,您有可能获得返回的页面。如果你可以分享一个带参数的示例 URL,我可以测试它。
      • 您可以使用WebUtility.UrlEncode对post参数进行编码。 __VIEWSTATE 应该被编码(因为默认填充:= 符号)。
      猜你喜欢
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 2015-05-31
      • 1970-01-01
      • 2015-10-23
      • 2014-04-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多