使用C#从API下载PDF文件

时间:2016-06-13 21:27:36

标签: c# .net asp.net-web-api

我正在创建一个

的控制台应用程序
  1. 连接供应商API以提取两个日期之间提交费用的凭证号码
  2. 下载使用费用
  3. 提交的收据的PDF副本

    第一部分,我工作得很好。我能够连接到Vendor API并解析返回的XML,以使用以下代码创建一个凭证编号数组(获取PDF图像所需):

    static async Task RunAsyncCR()
            {
                using (var client = new HttpClient())
                {
                    var values = new Dictionary<string, string>
                    {
                        {"un","SomeUser"},
                        {"pw","SomePassword"},
                        {"method","getVoucherInvoices"},
                        {"fromDate","05/30/2016"},
                        {"toDate", "06/13/2016"}
                    };
    
                    var content = new FormUrlEncodedContent(values);
    
                    Console.WriteLine("Connecting...");
    
                    var response = await client.PostAsync("https://www.chromeriver.com/receipts/doit", content);
    
                    Console.WriteLine("Connected...");
    
                    var responseString = await response.Content.ReadAsStringAsync();
    
                    char[] DelimiterChars = {'<'};
    
                    String[] xmlReturn = responseString.Split(DelimiterChars);
    
                    string[] VoucherNumber = new string[500];
    
                    int i = 0;
    
                    foreach (string s in xmlReturn)
                    {
                        if (s.Contains("voucherInvoice>") && s != "/voucherInvoice>\n    ")
                        {
                            VoucherNumber[i] = s.Substring(15, 16);
    
                            i++;
                        }
                    }
    
                    Array.Resize(ref VoucherNumber, i);
    

    是的,可能有更好的方法可以做到这一点,但它可以正常工作并返回我期望的值。

    现在,我遇到麻烦的是,当我连接回API以检索文件时,我似乎无法将文件下载到指定的文件路径。

    我可以使用

    连接回API
                i = 0;
    
                foreach (string x in VoucherNumber)
                {
                    Console.WriteLine("Get receipt: " + x);
    
                    var NewValues = new Dictionary<string, string>
                    {
                        {"un","SomeUser"},
                        {"pw","SomePassword"},
                        {"method","getReceiptsWithCoverPage"},
                        {"voucherInvoiceForPdf", VoucherNumber[i]}
                    };
    
                    var NewContent = new FormUrlEncodedContent(NewValues);
    
                    var NewResponse = await client.PostAsync("https://www.chromeriver.com/receipts/doit", NewContent);
    
                    string NewResponseString = await NewResponse.Content.ReadAsStringAsync();
    

    但我似乎无法将回复写入有效文件(PDF)

    这是我在单步执行代码时的Autos窗口的屏幕截图,我需要下载该文件:

    Autos

    我的问题是,从现在开始,如何将文件保存到我的系统?

    我尝试从执行Console.WriteLine(NewResponseString);获取编码响应并使用System.IO.File.WriteAllLines()方法使用指定的文件路径/名称将其写入文件,但这会导致空白文件。我还花了一些时间研究Google / Stackoverflow的深度,但不了解如何实现我找到的结果。

    非常感谢任何和所有帮助。

5 个答案:

答案 0 :(得分:10)

所以我认为你需要Streams的帮助。返回的HttpContent实际上是一个System.Net.Http.StreamContent实例,表明您正在获取内容。它只是从该实例获取Stream(内容)并将其保存到文件中。

var NewResponse = await client.PostAsync("https://www.chromeriver.com/receipts/doit", NewContent);

System.Net.Http.HttpContent content = NewResponse.Content; // actually a System.Net.Http.StreamContent instance but you do not need to cast as the actual type does not matter in this case

using(var file = System.IO.File.Create("somePathHere.pdf")){ // create a new file to write to
    var contentStream = await content.ReadAsStreamAsync(); // get the actual content stream
    await contentStream.CopyToAsync(file); // copy that stream to the file stream
    await file.FlushAsync(); // flush back to disk before disposing
}

我恭敬地建议你仔细阅读Streams的工作原理。这是许多语言中的常见结构,您可能需要在不久的将来再次处理。

答案 1 :(得分:2)

首先,你确定有一个文件开头吗?我建议使用开源库PdfSharp。我个人自己使用它,效果很好。至于下载文件,也许这可以帮助你...

同步下载

using System.Net;
WebClient webClient = new WebClient();
webClient.DownloadFile("http://example.com/myfile.txt", @"c:\\myfile.txt");

http://www.csharp-examples.net/download-files/

答案 2 :(得分:1)

首先从NewResponse创建StreamReader

Stream receiveStream = NewResponse.GetResponseStream ();
StreamReader readStream = new StreamReader (receiveStream, Encoding.UTF8);

然后定义StremaWriter以写入文件。

using (var writer = new StreamWriter(@"C:\MyNewFile.pdf", append: false))
{
    writer.Write(readStream.ReadToEnd());
}

替代方法是

var httpContent = NewResponse.Content; 

using(var newFile = System.IO.File.Create(@"C:\MyNewFile.pdf"))
{ 
    var stream = await httpContent.ReadAsStreamAsync();
    await stream.CopyToAsync(newFile);
}

答案 3 :(得分:0)

这是我所做的,没有找到满足我情况的其他解决方案:

using (var client = new System.Net.Http.HttpClient())

{
  client.DefaultRequestHeaders.Add("Authorization", "someapikey");
  client.BaseAddress = new Uri("https://someurl.com");
  byte[] bytes = client.GetByteArrayAsync(client.BaseAddress).ConfigureAwait(false).GetAwaiter().GetResult();

  
  string pdfFilePath = @"c:\somepath"
  System.IO.File.WriteAllBytes(pdfFilePath, bytes);

  //Note that below is only to open PDF in standard viewer, not necessary
  var process = new System.Diagnostics.Process();
  var startInfo = new System.Diagnostics.ProcessStartInfo()
{
    FileName=pdfFilePath,
    WorkingDirectory = System.IO.Path.GetDirectoryName(pdfFilePath),
    UseShellExecute = true
}

  process.StartInfo = startInfo;
  process.Start();

}

答案 4 :(得分:-1)

使用此代码从API下载pdf。它将字符串数据转换为字节并为您提供必要的解决方案。

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

request.ContentType = "application/pdf;charset=UTF-8";
request.Method = "GET";

using(HttpWebResponse response = (HttpWebResponse) request.GetResponse()) {

    BinaryReader bin = new BinaryReader(response.GetResponseStream());

    byte[] buffer = bin.ReadBytes((Int32) response.ContentLength);

    Response.Buffer = true;
    Response.Charset = "";

    Response.AppendHeader("Content-Disposition", "attachment; filename=+ filename); 

    Response.Cache.SetCacheability(HttpCacheability.NoCache);

    Response.ContentType = "application/pdf";

    Response.BinaryWrite(buffer);

    Response.Flush();

    Response.End();
}