【问题标题】:Downloading pdf file using WebRequests使用 WebRequests 下载 pdf 文件
【发布时间】:2012-08-10 12:09:41
【问题描述】:

我正在尝试根据 URL 列表自动下载一些 pdf 文件。

这是我的代码:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

request.Method = "GET";

var encoding = new UTF8Encoding();

request.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-gb,en;q=0.5");
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");

request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0";

HttpWebResponse resp = (HttpWebResponse)request.GetResponse();

BinaryReader reader = new BinaryReader(resp.GetResponseStream());

FileStream stream = new FileStream("output/" + date.ToString("yyyy-MM-dd") + ".pdf",FileMode.Create);

BinaryWriter writer = new BinaryWriter(stream);

while (reader.PeekChar() != -1)
      {
       writer.Write(reader.Read());
      }
       writer.Flush();
       writer.Close();

所以,我知道第一部分有效。我最初是使用 TextReader 获取它并阅读它 - 但这给了我损坏的 pdf 文件(因为 pdf 是二进制文件)。

现在,如果我运行它,reader.PeekChar() 始终为 -1,什么也没有发生 - 我得到一个空文件。

在调试它时,我注意到 reader.Read() 在我调用它时实际上给出了不同的数字 - 所以可能 Peek 坏了。

所以我尝试了一些非常肮脏的东西

try
{
 while (true)
   {
    writer.Write(reader.Read());
    }
 }
   catch
      {
      }
 writer.Flush();
 writer.Close();

现在我得到一个很小的文件,里面有一些垃圾,但它仍然不是我要找的。​​p>

那么,任何人都可以指出正确的方向吗?

附加信息:

标头不建议其压缩或其他任何内容。

HTTP/1.1 200 OK
Content-Type: application/pdf
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Fri, 10 Aug 2012 11:15:48 GMT
Content-Length: 109809

【问题讨论】:

    标签: c# pdf webrequest binaryreader


    【解决方案1】:

    跳过BinaryReaderBinaryWriter,只需将输入流复制到输出FileStream。简要介绍

    var fileName = "output/" + date.ToString("yyyy-MM-dd") + ".pdf";
    using (var stream = File.Create(fileName))
      resp.GetResponseStream().CopyTo(stream);
    

    【讨论】:

    • 我想知道是否有办法将它放入字节数组而不是将其发送到文件系统?
    • @ioSamurai:将File.Create(filename) 替换为new MemoryStream(),然后在using 块的末尾检索字节:var bytes = stream.ToArray()MemoryStream 不使用任何非托管资源,因此您也可以完全删除 using 块。
    • @MartinLiversage 嗯我已经尝试了几次,虽然我确实得到了一个字节流,但当我最终将它写入磁盘时,pdf文件已损坏......但是从浏览器发出相同的请求(我在代码中使用 WebRequest)可以很好地提供 PDF 文件。这实际上可能是一些奇怪的行为,与 Report Server 如何为 Web 请求提供 PDF 响应有关...
    • @ioSamurai:我很确定我提供的几行代码不会损坏 PDF 文件,如果 Report Server 有“奇怪的行为”,我会感到惊讶。要进行故障排除,您可以使用自己的代码比较文件的前几个字节和文件的长度,使用 Fiddler 等工具查看传输中的流和使用网络浏览器检索的文件。
    【解决方案2】:

    为什么不使用WebClient 类?

    using (WebClient webClient = new WebClient())
    {
        webClient.DownloadFile("url", "filePath");
    }
    

    【讨论】:

    【解决方案3】:

    您的问题是关于 WebClient,但您的代码显示您使用的是原始 HTTP 请求和响应。

    你为什么不实际使用System.Net.WebClient

    using(System.Net.WebClient wc = new WebClient()) 
    {
        wc.DownloadFile("http://www.site.com/file.pdf",  "C:\\Temp\\File.pdf");
    }
    

    【讨论】:

    • 抱歉,已修复原始问题。我选择原始 HTTP 请求/响应的原因是我需要自己修改标头。
    • 是的。它也这样做。刚刚在下面看到你的评论。生活和学习:-)
    【解决方案4】:
            private void Form1_Load(object sender, EventArgs e)
            {
      
                WebClient webClient = new WebClient();
                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
                webClient.DownloadFileAsync(new Uri("https://www.colorado.gov/pacific/sites/default/files/Income1.pdf"), @"output/" + DateTime.Now.Ticks ("")+ ".pdf", FileMode.Create);
            }
    
            private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
            {
                progressBar = e.ProgressPercentage;
            }
    
            private void Completed(object sender, AsyncCompletedEventArgs e)
            {
                MessageBox.Show("Download completed!");
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-12
      • 2017-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2016-04-07
      相关资源
      最近更新 更多