1. Setup .NET Web API code.
namespace MainWebService.Controllers { [ApiController] [Route("[controller]")] public class BuildController : ControllerBase { [HttpPost] [Route("[action]")] public Stream GetFile([FromBody] StringParamEntity parameters) { FileStream stream = System.IO.File.OpenRead(Path.Combine(System.IO.Directory.GetCurrentDirectory(), parameters.ParamString)); return stream; } } }
Nevermind the parameter for the method. Basically what the snippet says is you create a [FileStream] object and return it. You can you its base class [Stream] as the return type of the method.
2. Consume through HttpRequestMessage
public static async Task<Stream> CommonHTTPClientCodeForFileTransfer(HttpClient client, string baseURL, string webMethod, StringParamEntity parameters) { try { HttpResponseMessage hrm = await ReturnHttpStream(client, baseURL, webMethod, parameters); return await hrm.Content.ReadAsStreamAsync(); } catch(Exception ex) { Exception newEx = new Exception(ErrorMessageConstant.HTTP_CLIENT_FILE_STREAM_ERROR_MESSAGE, ex); throw newEx; } } private static Task<HttpResponseMessage> ReturnHttpStream(HttpClient client, string baseURL, string webMethod, StringParamEntity parameters) { string requestUrl = new Uri(new Uri(baseURL), webMethod).ToString(); JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings { DateFormatString = Constant.MY_DATETIME_FORMAT, DateFormatHandling = DateFormatHandling.IsoDateFormat }; string jsonData = JsonConvert.SerializeObject ( parameters, microsoftDateFormatSettings ); client.DefaultRequestHeaders.Accept.Clear(); if( parameters.ParamString.IndexOf(".dll", StringComparison.CurrentCultureIgnoreCase) > 0 ) client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-msdownload")); if (parameters.ParamString.IndexOf(".exe", StringComparison.CurrentCultureIgnoreCase) > 0) client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream")); if (parameters.ParamString.IndexOf(".zip", StringComparison.CurrentCultureIgnoreCase) > 0) client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/zip")); var request = new StringContent(jsonData, Encoding.UTF8, "application/json"); using (HttpRequestMessage rm = new HttpRequestMessage(HttpMethod.Post, requestUrl)) { rm.Content = request; return client.SendAsync(rm, HttpCompletionOption.ResponseHeadersRead); } }
Use the class instance of HttpRequestMessage instead of HttpClient. Use the HttpCompletion.ResponseHeadersRead enum argument for the second parameter of its SendAsync method. This is a key setting that will properly allow every byte to be recognized in the stream(in real time). Either this argument is not used or you went to using a different class (HttpClient) anyway it will not work, the file will be downloaded completely even before iterating per byte in the stream instance at the client side.
Nevermind the other code that is for the settings of JSON serialization.
3. WPF XAML
<StackPanel Grid.Row="1" Orientation="Vertical"> <TextBlock Text="{Binding StatusText}"></TextBlock> <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" Value="{Binding ByteTransfered}"></ProgressBar> </StackPanel>
Create the progress bar element and have the integer Value property binded to the View Model.
4. Finally, ViewModel code.
Task<Stream> tStream = CommonFunctions.CommonHTTPClientCodeForFileTransfer ( client, reg.DataSourceURLPath, "Build/GetFile", param2 ); await tStream; Stream st = tStream.Result; int length = f.ByteSize; byte[] result = new byte[length]; StatusText = f.FileName; string destinationPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constant.STEP_ASIA_MIS_INSTALLATION_FOLDER, f.FileName); byte[] bytes = new byte[length + 100000]; int numBytesToRead = (int)length; int numBytesRead do { int n = await st.ReadAsync(bytes, numBytesRead, 100000); numBytesRead += n; numBytesToRead -= n; StatusText = string.Format("{0} {1:0.##}%", f.FileName,((1.0 * numBytesRead) / length) * 100.0 ); ByteTransfered = CommonFunctions.ConvertToInt( (1.0 * numBytesRead / length) * 100 ); } while (numBytesToRead > 0); using (var fs = File.Create(destinationPath)) { fs.Write(bytes, 0, length); }
Hope you learned.