Reputation: 398
I am creating a console application that
The first part, I have working fine. I am able to connect to the Vendor API and parse out the returned XML to create an array of voucher numbers (needed to get the PDF images) using the following code:
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);
Yes, there is likely a better way of doing this, but it works and returns the values I am expecting.
Now, what I am having trouble with, is when I connect back to the API to retrieve the file, I cannot seem to be able to download the file to a specified file path.
I can connect back to the API using
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();
But I cannot seem to write the response to a valid file (PDF)
Here is a screen shot of my Autos window as I step through the code, where I would need to download the file:
My question is, from this point, how do I go about saving the file to my system?
I have tried to take the encoded response I get from doing Console.WriteLine(NewResponseString);
and write it to a file using the System.IO.File.WriteAllLines()
method, using a specified filepath/name, but this results in a blank file. I have also spent some time researching the depths of Google/Stackoverflow, but do not understand how to implement the results I find.
Any and all help would be greatly appreciated.
Upvotes: 7
Views: 44486
Reputation: 11
Here is what I did, did not find any other solution that satisfied my situation:
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();
}
Upvotes: 1
Reputation: 62213
So I think you need help with Streams. The returned HttpContent
is actually a System.Net.Http.StreamContent
instance which shows that you are getting content back. Its just a matter of getting the Stream (content) from that instance and saving that to a file.
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
}
I respectfully recommend that you do a little reading on how Streams work. This is a common construct in many languages that you will probably have to deal with again in the near future.
Upvotes: 16
Reputation: 27
Use this code for download a pdf from the API. It will convert the string data to bytes and provide you the necessary solution.
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();
}
Upvotes: 0
Reputation:
First of all, are you sure there is a file to begin with? May I suggest using the open source library PdfSharp. I personally use it myself and it works great. As far as downloading the file, maybe this may help you...
Download Synchronously
using System.Net;
WebClient webClient = new WebClient();
webClient.DownloadFile("http://example.com/myfile.txt", @"c:\\myfile.txt");
http://www.csharp-examples.net/download-files/
Upvotes: 2
Reputation: 195
At first Create StreamReader from NewResponse
Stream receiveStream = NewResponse.GetResponseStream ();
StreamReader readStream = new StreamReader (receiveStream, Encoding.UTF8);
Then Define a StremaWriter to write into a file.
using (var writer = new StreamWriter(@"C:\MyNewFile.pdf", append: false))
{
writer.Write(readStream.ReadToEnd());
}
Alternative Approach is
var httpContent = NewResponse.Content;
using(var newFile = System.IO.File.Create(@"C:\MyNewFile.pdf"))
{
var stream = await httpContent.ReadAsStreamAsync();
await stream.CopyToAsync(newFile);
}
Upvotes: 1