How to access secure url using webclient - c#

I am trying to access secure url via web client and getting few errors.
Overall purpose is download an image from secure url..
Please note that earlier, I was able to download image from repository with http and now they have enforced (security) https in same url.
We have a console application which runs on periodic basis and pulls image from server and stores locally.
Please advise as what I am doing wrong ? or what is missing ?
Following are the issues I am facing.
/// if I use code section 1... I get error saying Parameter is not valid.
/// if I use code section 2... File gets saved to local but get a message " File appear to be corrupt or large and not able to open.
Section 1 and 2 are listed below.
using (WebClient webClient = new WebClient())
{
webClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
webClient.Credentials = new NetworkCredential("id", "pwd"); // if credentials are wrong...still I get the imageByte
/// section 1 - if I use this code... I get error saying Parameter is not valid.
// ----------------------------- Start --------------------------------
imageByte = webClient.DownloadData("https://someurl/source/abcd.jpeg");
////Initialize image variable
Image newImage;
////Read image data into a memory stream
using (MemoryStream ms = new MemoryStream(imageByte, 0, imageByte.Length, true))
{
ms.Write(imageByte, 0, imageByte.Length);
//Set image variable value using memory stream.
newImage = Image.FromStream(ms, true, false); // Throws error at this line saying that parameter is not valid.
}
newImage.Save(#"location\image.jpeg");
// ----------------------------- End --------------------------------
/// section 2 - if I use this code... File gets saved to local but get a message " File appear to be corrupt or large and not able to open.
// ----------------------------- Start --------------------------------
webClient.DownloadFile("https://someurl/source/abcd.jpeg", #"location\image.jpeg");
// ----------------------------- End --------------------------------
}

Both errors say that the data which was downloaded is not a valid JPEG image. Likely it is because some error was returned from the server.
In order to check if server returned an error, you can take a look at what's in HTTP response headers and body.
For body you can just try to open a file saved in section 2 with a text editor.
For headers you can check webClient.ResponseHeaders property with debugger or with a simple update to your program.
Example below is taken from MSDN:
// Obtain the WebHeaderCollection instance containing the header name/value pair from the response.
WebHeaderCollection myWebHeaderCollection = myWebClient.ResponseHeaders;
Console.WriteLine("\nDisplaying the response headers\n");
// Loop through the ResponseHeaders and display the header name/value pairs.
for (int i=0; i < myWebHeaderCollection.Count; i++)
{
Console.WriteLine ("\t" + myWebHeaderCollection.GetKey(i) + " = " + myWebHeaderCollection.Get(i));
}
Another ways to see what was actually returned from the server are Invoke-WebRequest PowerShell cmdlet or wget utility (both should support HTTPS and authentication)

You're code works fine.
As Kel suggested most likely the server response header give may give an answer. Are you sure the server is configured to support https?
There is no need to give network credentials. Since HTTPS only is a transport protocol. It secures only the connection.
To do authentication you have to configure the server for example to do BASIC or DIGEST authentication. And if required setup authorization to the requested resource.
One comment on you're code: Don't forget to dispose newImage.

Related

Creating directory on server using HttpWebRequest

I am trying to create directory on server via https. But while returning the response it generates exceptions: “The remote server returned an error: (404) Not Found.”
The code is as follows:
string szURL3 = #"https://directoryurl/TestDir/";
//Create an HTTP request for the URL.
HttpWebRequest httpMkColRequest = (HttpWebRequest)WebRequest.Create(szURL3);
// Set up new credentials.
httpMkColRequest.Credentials = new NetworkCredential(_httpsUserName, _httpsPassword);
// Pre-authenticate the request.
httpMkColRequest.PreAuthenticate = true;
// Define the HTTP method.
httpMkColRequest.Method = #"MKCOL";
// Retrieve the response.
HttpWebResponse httpMkColResponse = (HttpWebResponse)httpMkColRequest.GetResponse();
//Write the response status to the console.
Console.WriteLine(#"MKCOL Response: {0}",httpMkColResponse.StatusDescription);
Could anybody support regarding this. I am able to get the directory information correctly in the same way. As I referred some links:
http://blogs.msdn.com/b/robert_mcmurray/archive/2011/10/18/sending-webdav-requests-in-net-revisited.aspx
According to this, what I understood is that the resources are locked. But how to unlock the resources for creating directory.
Please correct where modification required.
I solved the issue. The webDAV Configuration on the server was not enabled.

How to create and redeem coupons in Recurly, programmatically?

++++++++++++++
Actual Scenario: I am working on a site (ASP.Net using C#) where the system will have 3 different subscription plans i.e. monthly, quarterly and yearly. All the subscription plans have their own cost and pricing. Now, if the system/admin wants to give any discounts to any subscribed user (regardless of subscription plan) on their on-going subscription based on some business logic (for example, for some user it may be $4 and for other it may be $25). How can I achieve this goal. I tried PayPal and Recurly, but stuck in-between.
++++++++++++++
I have to create a coupon and redeem the same using Recurly dynamically in C#. But, as per the code mentioned in "https://docs.recurly.com/api/v1/subscription-plans", we have to use Recurly API v2, but we don't have the code to create and redeem the coupon. So, please help me on how can I create coupons and redeem the same.
When we are using below code in mentioned URL "Recurly PUT request working but returning server error", it causes error while getting response.
uri = "https://" + subdomain + ".recurly.com/v2/subscriptions/" + uuid + "/reactivate";
try
{
string xml = "<subscription><timeframe>now</timeframe></subscription>"; //also tried with blank string.
byte[] arr = System.Text.Encoding.UTF8.GetBytes(xml);
HttpWebRequest renewRequest = (HttpWebRequest)WebRequest.Create(uri);
renewRequest.Headers.Add("Authorization", "Basic " + encodeB64);
renewRequest.Method = "PUT";
renewRequest.ContentType = "text/XML";
renewRequest.ContentLength = arr.Length;
Stream datastream = renewRequest.GetRequestStream();
datastream.Write(arr, 0, arr.Length);
datastream.Close();
HttpWebResponse renewResponse = (HttpWebResponse)renewRequest.GetResponse();
}
Looking for kind response and help...
We (recurly.com) just made available a release candidate of an all new API client for C# compatible with Recurly APIv2 that we highly recommend using. The client API is stable and this release will shortly become the final release pending new show-stopping bugs.
Here's how to get started using it.
Be sure set up your configuration.
Here's how to create a coupon.
Here's how to redeem coupons.
More examples are available here.
If you have further questions please don't hesitate to ask our support team! support#recurly.com.

Exception in BackgroundUploader

I am trying to upload some avi file to server. It works fine with HttpRequest but i need to continue uploading even if i suspend app so thats why i am trying to use BackgroundUploader. I am following this guideline on msdn http://msdn.microsoft.com/en-us/library/windows/apps/jj152727.aspx. So my code looks something like this.
StorageFile storageFile = KnownFolders.VideosLibrary.GetFileAsync("fileName");
BackgroundUploader uploader = new BackgroundUploader();
uploader.Method = "POST";
uploader.SetRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
var fs = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
IInputStream aaaa = fs.GetInputStreamAt(0);
UploadOperation upload = uploader.CreateUploadFromStreamAsync(new Uri("uploadUri"), aaaa);
await HandleUploadAsync(upload, true);
the rest is same as on MSDN. And i am getting exception Unsupported media type (415) in method HandleUploadAsync on line
await upload.StartAsync().AsTask(cts.Token, progressCallback);
What am i doing wrong? Or what can cause this kind of exception?
EDIT : I solved my problem as i commented down here and in my answer. I think at the end i am basically just sending some data to server that are recognized and interpreted as i want to. So if i use BackgroundUploader i am not only uploading some file i am also sending information about how am i doing that(as i mentioned in my answer). So by the same idea i can also upload folder to server and by that i am not sending any actual content only some description about how to do that. And if i compare request that i am making by HttpRequest and BackgroundUploader they are equal and thats what i wanted.
So the problem part was the header of request. I have some header in my request that is recognized by server and i was trying to put it to BackgroundUploader through SetRequestheader method but it did not work. As Kieqic suggested i used Fiddler and by that i compare request made by HttpRequest and BackgroundUploader. I found out they are completely different. So through SetRequestheader i add some parts like expected Content-Type and for the rest parts of header to make them equal i add it before content of my file as array of bytes. And this works so conclusion is in my case using Fiddler that helped my how to construct request header.

Detect that a PHP link causes a file download in c#

I can't seem to find a working answer to my problem and I wonder if someone out there can help. Basically I have a link on my website which causes a zip file to be downloaded:
http://***.com/download.php?id=1
If you activate this link on the web page it will bring up a save as dialog and lets you save the file with default name ThisIsMyZipFile.zip
My problem is that under c# If I use new Uri("http://***.com/download.pgp?id=1").IsFile it returns false so I cannot seem to detect that this is a file without performing a webclient DownloadString and seeing if the first two bytes are PK.
Also even if manually download as a string detect the PK header and save the file I cannot find out what my web site wants to use as the default filename being ThisIsMyZipFile.zip in this example as I want to use the same filename.
Does anyone know a nice way of solving these two problems please?
UPDATE
Thanks to Paul and his answer I created the following function which does exactly what I need:
/// <summary>
/// Returns the responded HTTP headers of the given URL and if the link refers to the file it returns extra information about it.
/// </summary>
/// <param name="Url">The address.</param>
/// <returns>
/// null if a WebException is thrown
/// otherwise:
/// List of headers:
/// Keep-Alive - Timeout value (i.e. timeout=2, max=100)
/// Connection - The type of connection (i.e. Keep-Alive)
/// Transfer-Encoding - The type of encoding used for the transfer (i.e. chunked)
/// Content-Type - The type of Content that will be transferred (i.e. application/zip)
/// Date - The servers date and time
/// Server - The server that is handling the request (i.e. Apache)
/// AbsoluteUri - The full Uri of the resulting link that will be followed.
/// The following key will be present if the link refers to a file
/// Filename - The filename (not path) of the file that will be downloaded if the link if followed.
/// </returns>
public Dictionary<string, string> GetHTTPResponseHeaders(string Url)
{
WebRequest WebRequestObject = HttpWebRequest.Create(Url);
WebResponse ResponseObject = null;
try
{
ResponseObject = WebRequestObject.GetResponse();
}
catch(WebException ex)
{
return null;
}
// Add the header inforamtion to the resulting list
Dictionary<string, string> HeaderList = new Dictionary<string, string>();
foreach (string HeaderKey in ResponseObject.Headers)
HeaderList.Add(HeaderKey, ResponseObject.Headers[HeaderKey]);
// Add the resolved Uri to the resulting list
HeaderList.Add("AbsoluteUri", ResponseObject.ResponseUri.AbsoluteUri);
// If this is a zip file then add the download filename specified by the server to the resulting list
if (ResponseObject.ContentType.ToLower() == "application/zip")
{
HeaderList.Add("Filename", ResponseObject.ResponseUri.Segments[ResponseObject.ResponseUri.Segments.Length-1]);
}
// We are now finished with our response object
ResponseObject.Close();
// Return the resulting list
return HeaderList;
}
Uri.IsFile performs a static check upon the URI, i.e. it sees whether the 'scheme' part (the first bit including the colon) is file:. It does not look at the actual content returned by requesting the resource that resides at the URI. (In fact, because it does not actually attempt to contact the server at all, the URI could actually point to a missing resource and yet IsFile would still work.)
If you wish to see if the content of the resource is of a particular type then you will have to either:
Retrieve the HTTP header for the resource (if it is an HTTP or HTTPs resource: that is, if the 'scheme' is http or https).
Retrieve (at least part of) the resource and examine it.
You are currently doing 2, but for an HTTP resource (with an HTTP URL) then it would be cleaner and cheaper to do 1. You can do this by performing an HTTP HEAD request (as opposed to GET or POST, &c.). This will return the HTTP headers without returning the resource itself. The code would look something like:
var request = WebRequest.Create("http://somewhere.overtherainbow.com/?a=b");
request.Method = "HEAD";
WebResponse response = request.GetResponse();
//TODO check status code
string contentType = response.ContentType;
response.Close();
The content type will give you some indication of the file type, but many binary files will just be returned as an octet stream, so you may still need to retrieve and examine the magic bytes of the resource itself if you wish to differentiate between different binary file types. (The content type should be sufficient for you to differentiate between a binary file and a web page though.)
So, a full solution may be:
Send a GET request for the resource.
Check the response status to make sure there was no error.
Check the content type header to see if we have a binary octet stream.
Read two bytes from the response stream to see if it the file starts 'PK'.
You absolutely cannot detect that a given URL would cause a file to be downloaded without actually sending an HTTP request to this url.
Now to the second problem. You could send an HTTP request to download the file and then inspect the Content-Disposition header which will contain the filename:
using (var client = new WebClient())
{
using (var stream = client.OpenRead("http://*.com/download.php?id=1"))
{
var disposition = client.ResponseHeaders["Content-Disposition"];
if (disposition != null)
{
var cd = new ContentDisposition(disposition);
if (!cd.Inline && !string.IsNullOrEmpty(cd.FileName))
{
using (var outputStream = File.OpenWrite(cd.FileName))
{
stream.CopyTo(outputStream);
}
}
}
else
{
// The web server didn't send a Content-Disposition response header
// so we have absolutely no means of determining the filename
// you will have to use some default value here if you want to store it
}
}
}

Save Webcam Image From Website

There is a website that posts a image from their webcam that I would like to be able to grab using a program. How would I get this jpeg data in memory? I have tried HttpRequest but it only returns html.
Here is the link:
http://bigwatersedge.axiscam.net/view/snapshot.shtml?picturepath=/jpg/image.jpg
Image source is at this URL:
http://bigwatersedge.axiscam.net/jpg/image.jpg?timestamp=
Use WebClient to save the data.
WebCleint wc = new WebClient();
byte[] data = wc.DownloadData("http://bigwatersedge.axiscam.net/jpg/image.jpg?timestamp=");
The URL of the image is actually http://bigwatersedge.axiscam.net/jpg/image.jpg?timestamp=. The URL you gave returns a page with an image on it.
Now, once you are downloading the correct URL of the image, this particular server is checking your HTTP referer. Put this in your HTTP headers:
Referer: http://bigwatersedge.axiscam.net/view/snapshot.shtml?picturepath=/jpg/image.jpg
I am working with Robert, the original poster on this, and have a problem getting to that URL with the image. If the URL is pasted in the browser:
403 Forbidden
Your client does not have permission to get Images/Streams from this server.
Which is new, I was getting the URL text repeated in the browser:
http://bigwatersedge.axiscam.net/jpg/image.jpg?timestamp=
WebClient throws and exception:
"The underlying connection was closed: The connection was closed unexpectedly."
I also added:
WebHeaderCollection headerCollection = new WebHeaderCollection();
headerCollection.Add("http://bigwatersedge.axiscam.net/view/snapshot.shtml?picturepath=/jpg/image.jpg");
wc.Headers = headerCollection;
Basically, I am having trouble retrieving the image in the URL.
update:
I added the HttpRequestHeader.Referer to the header collection.
No exception throw, collects the image data. Have not converted the byte array to a workable image object yet.

Categories