I am trying from a .net client to download a file via a .net server (file is located on server machine ) using the StreamContent.However when launching the request i am getting the exception:
Exception
Stream does not support reading.
Client
class Program {
static async Task Main(string[] args) {
HttpClient client = new HttpClient();
using (FileStream stream = new FileStream("txt.path", FileMode.OpenOrCreate, FileAccess.Write)) {
var content = new StreamContent(stream);
var response = await client.PostAsync("http://localhost:5300/get", content);
}
}
}
Server
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
string fname = "dld.txt";
app.Run(async (context) => {
if (!(context.Request.Path == "get")) {
return;
}
File.WriteAllText(fname, "data is:" + DateTime.Now.ToString());
FileStream fs = new FileStream(fname, FileMode.Open, FileAccess.Read);
using (Stream stream = context.Response.Body) {
await fs.CopyToAsync(stream);
}
});
}
Hi you can use like this:
HttpContent stringContent = new StringContent(paramString); //if you want to use string
HttpContent fileStreamContent = new StreamContent(paramFileStream); //if you want to use file stream
HttpContent bytesContent = new ByteArrayContent(paramFileBytes);// if you want to use aray of bytes
using (var client = new HttpClient())
{
using (var formData = new MultipartFormDataContent())
{
formData.Add(stringContent, "param", "param");
formData.Add(fileStreamContent, "file", "file");
formData.Add(bytesContent, "file", "file");
var response = await client.PostAsync("some URL", formData);
if (!response.IsSuccessStatusCode)
{
return null;
}
return await response.Content.ReadAsStreamAsync();
}
}
I was having trouble getting the file because i wanted to use the Request.Body stream as a sink.I wanted the server to write the data on this stream (i thought the Request stream can be used both ways).
I have solved it by using the Response stream instead:
Client
static async Task Main(string[] args) {
HttpClient client = new HttpClient();
using (FileStream stream = new FileStream("data.txt", FileMode.OpenOrCreate, FileAccess.Write)) {
var content = new StringContent("not important");
var response = await client.PostAsync("http://localhost:5300/get",content);
await response.Content.CopyToAsync(stream);
}
}
Related
Direct to the point: I want to download and save a .pdf file so that the user can see it later in the Media Library.
I'm looking for a way to achieve this in Windows Phone 8 Silverlight.
Here is the code I'm using right now:
private void DownloadPDF(string url)
{
var client = new WebClient();
client.OpenReadCompleted += client_OpenReadCompleted;
this.FileName = Path.GetFileName(url);
client.OpenReadAsync(new Uri(url));
}
async void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
// Save file:
var buffer = new byte[e.Result.Length];
await e.Result.ReadAsync(buffer, 0, buffer.Length);
using (var storageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var stream = storageFile.OpenFile(this.FileName, FileMode.Create))
{
await stream.WriteAsync(buffer, 0, buffer.Length);
}
}
// Open file:
var local = ApplicationData.Current.LocalFolder;
var pdffile = await local.GetFileAsync(this.FileName);
Windows.System.Launcher.LaunchFileAsync(pdffile);
var progressIndicator = new ProgressIndicator()
{
IsVisible = false
};
SystemTray.SetProgressIndicator(this, progressIndicator);
}
Thank you very much!
I write a Datetime string in a file and after that try to read it back, but string returns interlaced with zero characters. WP Power tools show string intact "18.02.2015 12:08:17". But after reading it looks like:
"1\08\0.\00\02\0.\02\00\01\05\0 \01\02\0:\00\08\0:\01\07\0"
await FileExtensions.WriteDataToFileAsync("scheduleDateTime.txt", scheduleTime);
var contents = await FileExtensions.ReadFileContentsAsync("scheduleDateTime.txt");
public static async Task<String> ReadFileContentsAsync(string fileName)
{
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
if (local != null)
{
var file = await local.OpenStreamForReadAsync(fileName);
using (StreamReader streamReader = new StreamReader(file))
{
return streamReader.ReadToEnd();
}
}
else
{
return String.Empty;
}
}
public static async Task WriteDataToFileAsync(string fileName, string content)
{
byte[] data = Encoding.Unicode.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}
You're saving the file by using UTF-16 encoding, but reading it back using the default encoding (that is, UTF-8). You need to use the same encoding for both case.
Usually, the recommandation is to use UTF-8 to read and write in files, so you need to change your WriteDataToFileAsync method:
public static async Task WriteDataToFileAsync(string fileName, string content)
{
byte[] data = Encoding.UTF8.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}
I have been trying to send a image to restful service and some data with it. But i can send data (Name and Description of image) and also i created sql database to store data and data is added on it but i can't send image to the server.
the code for service:
[WebInvoke(UriTemplate = "UploadPhoto/{fileName}/{description}", Method = "POST")]
public void UploadPhoto(string fileName, string description, Stream fileContents)
{
byte[] buffer = new byte[32768];
MemoryStream ms = new MemoryStream();
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileContents.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
ms.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
// Save the photo on database.
using (DataAcess data = new DataAcess())
{
var photo = new Photo() { Name = fileName, Description = description, Data = ms.ToArray(), DateTime = DateTime.UtcNow, };
data.InsertPhoto(photo);
}
ms.Close();
Console.WriteLine("Uploaded file {0} with {1} bytes", fileName, totalBytesRead);
}
And this is my code on client side. I am doing it on windows phone 7.
void btnNewPhoto_Click(object sender, RoutedEventArgs e)
{
Uri uri = new Uri("http://localhost:2557/photos");
string requestUrl = string.Format("{0}/UploadPhoto/{1}/{2}", uri, System.IO.Path.GetFileName(txtFileName.Text), txtDescription.Text);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
request.Method = "POST";
request.BeginGetRequestStream
(result =>
{
// Sending the request.
using (var requestStream = request.EndGetRequestStream(result))
{
using (StreamWriter writer = new StreamWriter(requestStream))
{
BinaryReader reader = new BinaryReader(requestStream);
string s = imgPhoto.ToString();
byte[] byteArray = Encoding.UTF8.GetBytes(s.ToString());
requestStream.Write(byteArray, 0, byteArray.Length);
requestStream.Close();
requestStream.Dispose();
//writer.Write(requestUrl);
//writer.Flush();
}
}
// Getting the response.
request.BeginGetResponse(responseResult =>
{
var webResponse = request.EndGetResponse(responseResult);
using (var responseStream = webResponse.GetResponseStream())
{
using (var streamReader = new StreamReader(responseStream))
{
string srresult = streamReader.ReadToEnd();
}
}
}, null);
}, null);
}
I'm trying to call the google URL shortner API from a WP7 app, I tried first on a Console Application by doing this:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/urlshortener/v1/url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"longUrl\":\"http://www.google.com/\"}";
Console.WriteLine(json);
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
Console.WriteLine(responseText);
}
Console.Read();
and it worked fine, and returned everything OK, but when I try to do it on a Windows Phone App like this:
private void button1_Click(object sender, RoutedEventArgs e)
{
testConnection();
}
private void testConnection()
{
if (!NetworkInterface.GetIsNetworkAvailable())
MessageBox.Show("There's no internet connection, please reconnect to the internet and try again");
else
{
var req = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/urlshortener/v1/url");
req.ContentType = "application/json";
req.Method = "POST";
req.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), req);
textBlock2.Text = "Done";
}
}
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
// Create the post data
// Demo POST data:
string postData = "http://www.google.com";
byte[] byteArray = Encoding.Unicode.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
void GetResponseCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
textBlock1.Text= streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
}
catch (WebException e)
{
}
}
The code always goes to the catch of the try method and gives "not found" error.
There is a known issue with SSL and not-trusted certificates. Connection to a web site with SSL that require ClientCertificates is not supported in the current Windows Phone 7 application model (Only BasicAuthentication is supported). You can read about the same problem here: http://forums.create.msdn.com/forums/p/65076/398730.aspx
I had a similar issue (which makes sense since I started out with this code as my example...) and when I changed the following code it started working to the point where I could progress forward again.
... from:
byte[] byteArray = Encoding.Unicode.GetBytes(postData);
... to (the equivalent of):
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
I've been dying for about 6 hours trying to figure out how to make a regular POST request in WP7 , I tried the answers of similar questions posted here and on many other places, I also tried many different APIs POST request, they all lead to one certain problem,
The remote server returned an error: NotFound.
it seems like everytime there's something missing.
So, if you please someone show us how to properly get a POST request right in this WP7
I use this to post to facebook without any problem:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
request.Method = "POST";
request.BeginGetResponse((e) =>
{
try
{
WebResponse response = request.EndGetResponse(e);
// Do Stuff
}
catch (WebException ex)
{
// Handle
}
catch (Exception ex)
{
// Handle
}
}, null);
I assume you would have tried this already so it may be something to do with the post data (which isn't in the above example as facebook uses the query string). Can you give us any more info?
EDIT: This is an (untested) example for writing post data:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
request.Method = "POST";
request.BeginGetRequestStream((e) =>
{
using (Stream stream = request.EndGetRequestStream(e))
{
// Write data to the request stream
}
request.BeginGetResponse((callback) =>
{
try
{
WebResponse response = request.EndGetResponse(callback);
// Do Stuff
}
catch (WebException ex)
{
// Handle
}
catch (Exception ex)
{
// Handle
}
}, null);
}, null);
I use the following class for making POST requests with WP7:
public class PostMultiPartFormData
{
private Dictionary<string, object> Parameters;
private Encoding ENCODING = Encoding.UTF8;
private string BOUNDARY = "-----------------------------wp7postrequest";
public event EventHandler PostComplete;
public void Post(string postbackURL,
Dictionary<string, object> parameters)
{
Parameters = parameters;
Uri url = null;
url = new Uri(postbackURL);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=" + BOUNDARY;
request.BeginGetRequestStream(new AsyncCallback(SendStatusUpdate), request);
}
private void SendStatusUpdate(IAsyncResult ar)
{
HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
Stream stream = request.EndGetRequestStream(ar);
byte[] byteArray = GetMultipartFormData(Parameters, BOUNDARY);
stream.Write(byteArray, 0, byteArray.Length);
stream.Close();
stream.Dispose();
request.BeginGetResponse(new AsyncCallback(StatusUpdateCompleted), request);
}
private byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
{
Stream formDataStream = new System.IO.MemoryStream();
foreach (var param in postParameters)
{
if (param.Value is byte[])
{
byte[] fileData = param.Value as byte[];
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}.jpg\";\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, param.Key, param.Key);
formDataStream.Write(ENCODING.GetBytes(header), 0, header.Length);
formDataStream.Write(fileData, 0, fileData.Length);
}
else
{
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, param.Key, param.Value);
byte[] b = ENCODING.GetBytes(postData);
foreach (var item in b)
{
formDataStream.WriteByte(item);
}
}
}
string footer = "\r\n--" + boundary + "--\r\n";
byte[] footerbytes = ENCODING.GetBytes(footer);
formDataStream.Write(footerbytes, 0, footerbytes.Length);
formDataStream.Position = 0;
byte[] formData = new byte[formDataStream.Length];
formDataStream.Read(formData, 0, formData.Length);
formDataStream.Flush();
formDataStream.Close();
return formData;
}
private void StatusUpdateCompleted(IAsyncResult ar)
{
if (PostComplete != null)
{
PostComplete(ar, null);
}
}
}
Example:
PostMultiPartFormData postRequest = new PostMultiPartFormData();
postRequest.PostComplete += new EventHandler( (sender, e) =>
{
IAsyncResult ar = ((IAsyncResult)sender);
using (WebResponse resp = ((HttpWebRequest)ar.AsyncState).EndGetResponse(ar))
{
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string responseString = sr.ReadToEnd();
this.Dispatcher.BeginInvoke(() =>
{
textBlock.Text = responseString;
});
}
}
});
postRequest.Post("http://localhost:50624/SSLProxy.ashx",
new Dictionary<string, object>() { { "param1", "value1" } });
This should work...
If it doesn't let me know! :-)
For easier access to advanced http features check out these http classes:
http://mytoolkit.codeplex.com/wikipage?title=Http
It encapsulates GET, POST, FILES (using path or Stream objects) and GZIP (not directly supported by WP7) requests.
To add post data just call BeginGetRequestStream method (also, BeginGetResponse move to GetRequestStreamCallback)
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
// Create the post data
string postData = "post data";
byte[] byteArray = Encoding.Unicode.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
I recommend you to use the postclient. It is pretty simple. You just need to add reference to dll file into your project, and then write something like:
public void authorize(string login, string password)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("command", "login");
parameters.Add("username", login);
parameters.Add("password", password);
PostClient proxy = new PostClient(parameters);
proxy.DownloadStringCompleted += (sender, e) =>
{
if (e.Error == null)
{
MessageBox.Show(e.Result);
}
};
proxy.DownloadStringAsync(new Uri("http://address.com/service", UriKind.Absolute));
}