c# files downloaded with httpwebrequest and cookies get corrupted - c#

I am trying to make a program which is able to download files with URI(URL) using httpwebrequest and cookies(for credential information to keep login status).
I can download files with following code but files get corrupted after being downloaded.
when I download xlsx file(on the web page) into text file at local drive, I see some part of numbers and words from an original file in a corrupted file, therefore I assume I have reached to the right file.
however, when I download xlsx file(on the web page) in xlsx file at local drive, it seems like it fails to open saying
excel cannot open the file 'filename.xlsx' because the file format or
file extension is not valid. Verify that the file has not been
corrupted and that the file extension matches the format of the file.
Is there any way I can keep fully original file content after I download?
I attach a part of result content as well.
private void btsDownload_Click(object sender, EventArgs e)
{
try
{
string filepath1 = #"PathAndNameofFile.txt";
string sTmpCookieString = GetGlobalCookies(webBrowser1.Url.AbsoluteUri);
HttpWebRequest fstRequest = (HttpWebRequest)WebRequest.Create(sLinkDwPage);
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 = ssItemLinkDwPage;
HttpWebRequest hwrRequest = (HttpWebRequest)WebRequest.Create(sUrl);
hwrRequest.Method = "POST";
string sPostData = "__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=" + sViewState + "&__EVENTVALIDATION=" + sEventValidation + "&Name=test" + "&Button1=Button";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bByteArray = encoding.GetBytes(sPostData);
hwrRequest.ContentType = "application/x-www-form-urlencoded";
Uri convertedURI = new Uri(ssDwPage);
hwrRequest.CookieContainer = new System.Net.CookieContainer();
hwrRequest.CookieContainer.SetCookies(convertedURI, 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(filepath1, FileMode.OpenOrCreate, FileAccess.Write);
Byte[] info = encoding.GetBytes(sResponseFromServer);
fs.Write(info, 0, info.Length);
fs.Close();
reader.Close();
sDataStream.Close();
response.Close();
}
}
}
}
catch
{
MessageBox.Show("Error");
}
}

StreamReader is for dealing with text data. Using it corrupts your binary data(excel file).
Write sDataStream directly to file. For ex.
sDataStream.CopyTo(fs)
PS: I prepared a test case (using similar logic) to show how your code doesn't work
var binaryData = new byte[] { 128,255 };
var sr = new StreamReader(new MemoryStream(binaryData));
var str3 = sr.ReadToEnd();
var newData = new ASCIIEncoding().GetBytes(str3); //<-- 63,63
Just compare binaryData with newData

Related

C# - Trying to grab and save a pdf into my database

In my C# application, I am trying to make it able to pull a pdf and save it, so that end users can press a button and pull up that pdf while they are in the application. But when I copy the content to the filestream it makes the pdf but it is just blank with nothing from the original pdf. What am I doing wrong?
The pdf's could also have pictures on them, and I don't think the way I'm doing it would allow those to be brought over.
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
bool? response = openFileDialog.ShowDialog();
var fileContent = string.Empty;
var filestream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(filestream))
{
fileContent = reader.ReadToEnd();
}
// make folder path
string FolderPath = "ProjectPDFs\\";
string RootPath = "X:\\Vents-US Inventory";
DirectoryInfo FolderDir = new DirectoryInfo(Path.Combine(RootPath, FolderPath));
Directory.CreateDirectory(FolderDir.ToString());
string filePath = "";
string FileName = openFileDialog.SafeFileName;
if (fileContent.Length > 0)
{
filePath = Path.Combine(FolderDir.ToString(), FileName);
using (Stream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
byte[] bytestream = Encoding.UTF8.GetBytes(fileContent);
Stream stream = new MemoryStream(bytestream);
stream.CopyTo(fileStream);
}
}

Uploading file to azure file share from azure function app

I have a function app and azure fileshare. I want to upload a file from internet using the url to my azure file share storage.
private ShareFileClient GetShareFile(string filePath)
{
string connectionString = "My connection string";
return new ShareFileClient(connectionString, "temp", filePath);
}
ShareFileClient destFile = GetShareFile(filePath);
// Start the copy operation
await destFile.StartCopyAsync(new Uri(DownloadUrl));
But this code is not working as expected. It is throwing error "Unauthorized
RequestId:000db1ff-801a-000a-0602-b24449000000
Time:2020-11-03T16:58:36.5697281Z
Status: 401 (Unauthorized)
ErrorCode: CannotVerifyCopySource" . Any helps will be highly appreciated
A simple code to write and read:
string con_str = "DefaultEndpointsProtocol=https;AccountName=0730bowmanwindow;AccountKey=xxxxxx;EndpointSuffix=core.windows.net";
string sharename = "test";
string filename = "test.txt";
string directoryname = "testdirectory";
ShareServiceClient shareserviceclient = new ShareServiceClient(con_str);
ShareClient shareclient = shareserviceclient.GetShareClient(sharename);
ShareDirectoryClient sharedirectoryclient = shareclient.GetDirectoryClient(directoryname);
//write data.
ShareFileClient sharefileclient_in = sharedirectoryclient.CreateFile(filename,1000);
string filecontent_in = "This is the content of the file.";
byte[] byteArray = Encoding.UTF8.GetBytes(filecontent_in);
MemoryStream stream1 = new MemoryStream(byteArray);
stream1.Position = 0;
sharefileclient_in.Upload(stream1);
//read data.
ShareFileClient sharefileclient_out = sharedirectoryclient.GetFileClient(filename);
Stream stream2 = sharefileclient_out.Download().Value.Content;
StreamReader reader = new StreamReader(stream2);
string filecontent_out = reader.ReadToEnd();
Above code works fine on my side, you just need to convert file to stream first.

Can't convert UTF8 to default encoding

I am trying to download a file over a RESTful Webservice and then save the file on the computer.
I am using an PDF-File to test the code. I found out the data is UTF-8 encoded so i tried encoding it back to default, because i found out by reading the pdf file locally and writing it back again that it works that way.
Here is my code:
IConsumerRequest getDocumentRequest = class.consumerSession
.Request()
.ForMethod("GET")
.ForUri(new Uri(class.apiEndpoint + "/1/documents/" + id))
.SignWithToken(class.accessToken);
string test = System.IO.File.ReadAllText("C:\\test.pdf", Encoding.Default);
byte[] bytes = Encoding.UTF8.GetBytes(getDocumentRequest.ToString());
string data = Encoding.Default.GetString(bytes);
MessageBox.Show(test.Substring(0, 120) + "\n\n" + data.Substring(0, 120));
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.FileName = dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
System.IO.File.WriteAllBytes(saveFileDialog.FileName, bytes);
}
Comparing the string shows the following (second line):
Local String vs String from Webservice
I already tried several ways to convert the string without any difference.
You can use the Encoding.Convert method.
byte[] converted = Encoding.Convert(Encoding.UTF8, Encoding.Default, bytes);
Got it to work with HttpWebResponse:
HttpWebResponse webResponse = getDocumentRequest.ToWebResponse();
Stream stream = webResponse.GetResponseStream();
Encoding enc = System.Text.Encoding.GetEncoding(UTF8);
StreamReader loResponseStream = new StreamReader(webResponse.GetResponseStream(), enc);
string serverResponse = loResponseStream.ReadToEnd();
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.FileName = dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
System.IO.File.WriteAllText(saveFileDialog.FileName, serverResponse, Encoding.Default);
}

Download PDF File from API Using C#

I am creating a console application that
Connects to a vendor API to pull voucher numbers for submitted expenses between two dates and
Downloads a PDF copy of receipts submitted with the expense
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.
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.
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/
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);
}
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();
}
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();
}

Dynamically Create PDF file and Bind to Pdf Viewer control

I am generating an ssrs report in my Silverlight application and I need to convert the ssrs report to RadPDFViewer control(telerik silverlight).
So I am saving the pdf file in the project folder using WCF.
Now i need to read the file again and bind it to Pdfviewer.
Saving happens asynchronously.
How should I wait untill the file is saved and then read from the folder?
Also, can you please show me how to read the PDF as a Memory stream.
I run the following code unsuccessfully.
public byte[] ReturnPdf(string requestUrl) {
HttpWebRequest req = null; var buf = new byte[1024];
try
{
req = (HttpWebRequest)WebRequest.Create(requestUrl);
req.Credentials = CredentialCache.DefaultCredentials;
req.Method = "GET"; var objResponse = req.GetResponse();
var stream = objResponse.GetResponseStream();
if (stream != null){BinaryReader br = new BinaryReader(stream);
buf = br.ReadBytes(1024);
} if
(stream != null) stream.Close();
}
catch Exception e){}return buf;
}
private void button2_Click(object sender, EventArgs e)
{
string baseUrl = "http://abc/ReportServer&rs:Command=Render&rs:ClearSession=true&rs:Format=PDF";
const string nullString = ":isnull=true";
byte[] o = ReturnPdf(baseUrl);
byte[] bytes = new byte[1024];
Stream s = new MemoryStream(bytes);
}
Write PDF Stream:
Write PDF stream to response stream
You could check to see if the file has been written completely.
How to test if a file is currently being written to
Or this might help:
How to check for file lock?

Categories

Resources