Reputation: 2264
I'm building a Xamarin app. I'm still on a very very noobish level, and I'm coming from Nativescript, and something (not much) of Native Android.
I have an Express server that performs long-time operations. During that time the Xamarin client waits with a spinner.
On the server I already calculate the percentage progress of the job, and I'd like to send it to the client each time it changes, in order to swap that spinner with a progress.
Still, on the server, the task was already achieved with a
response.write('10');
where the number 10 stands for "10%" of the Job done.
Now the tuff part. How can I read that 10 from the stream? Right now it works as a JSON response, because it waits for the whole response to come.
// Gets weather data from the passed URL.
async Task<JsonValue> DownloadSong(string url)
{
// Create an HTTP web request using the URL:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
// Send the request to the server and wait for the response:
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (System.IO.Stream stream = response.GetResponseStream())
{
// Use this stream to build a JSON document object:
JsonValue jsonDoc = await Task.Run(() => JsonValue.Load(stream));
// Return the JSON document:
return jsonDoc;
}
}
}
The server writes on the response each time the progress of the job changes, sending a plain string containing the percentage value. At the end of the job, it will write a final string, which will be a Base64 (very long) string. And the response will be then closed.
Can anyone indicate me how to change that script in order to read each data chunk the server sends?
Upvotes: 4
Views: 3542
Reputation: 101613
First you need to define some protocol. For simplicity we can say that server sends:
So, valid response is, for example, "010020050090100{..json here..}".
Then you can read response in 3-byte chunks, until you find "100". Then you read json. Sample code:
using (System.IO.Stream stream = response.GetResponseStream()) {
while (true) {
// 3-byte buffer
byte[] buffer = new byte[3];
int offset = 0;
// this block of code reliably reads 3 bytes from response stream
while (offset < buffer.Length) {
int read = await stream.ReadAsync(buffer, offset, buffer.Length - offset);
if (read == 0)
throw new System.IO.EndOfStreamException();
offset += read;
}
// convert to text with UTF-8 (for example) encoding
// need to use encoding in which server sends
var progressText = Encoding.UTF8.GetString(buffer);
// report progress somehow
Console.WriteLine(progressText);
if (progressText == "100") // done, json will follow
break;
}
// if JsonValue has async api (like LoadAsync) - use that instead of
// Task.Run. Otherwise, in UI application, Task.Run is fine
JsonValue jsonDoc = await Task.Run(() => JsonValue.Load(stream));
return jsonDOc;
}
Upvotes: 2