Download and save an HttpRequestMessage C# - c#

In my WP8.1 Silverlight app, I want to download a file and save it to an isolated storage. The downloading is OK, but how I can save it ?
For the downloading, I use this :
var HttpClientDownloadFile = new Windows.Web.Http.HttpClient();
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Get, new Uri(downloadUrl));
request.Headers.Add("Range", "bytes=0-");
// Hook up progress handler.
Progress<HttpProgress> progressCallback = new Progress<HttpProgress>(OnSendRequestProgress);
var tokenSource = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await HttpClientDownloadFile.SendRequestAsync(request).AsTask(tokenSource.Token, progressCallback);
If I run the debug, in response.content I have my download. Now, I want to save it to the isolated storage. How can I do that ? Should I use an stream ?
Thanks

Convert your response to stream and write it to file
using (var fileStream = await this.storageFile.OpenFileAsync(fileName, FileMode.OpenOrCreate))
{
await stream.CopyToAsync(fileStream);
}

Related

.NET Core 3 MVC download a file from HTTP and re-deliver to client using minimum memory

I have a .NET Core 3 MVC app that needs to read a file from one location over HTTP and then re-deliver it back out to the response. Some of these files will be ~200MB in size.
What I have works, but it reads the whole file into memory before sending the File result out to the client. Is there a way to make it essentially a passthrough where the read stream flows into the response stream so that very little memory is required on the server?
This is what I have now but I do not think will perform well with large files:
if (requestedFile != null)
{
using (var client = new System.Net.Http.HttpClient())
{
using (var result = await client.GetAsync(requestedFile.DownloadUrl))
{
if (result.IsSuccessStatusCode)
{
var bytes = await result.Content.ReadAsByteArrayAsync();
return File(bytes, "application/zip", "largefile.zip");
}
}
}
}
I have also tried this which results in a runtime error of "Cannot access a closed Stream":
using (var client = new System.Net.Http.HttpClient())
{
using (var httpResponseMessage = await client.GetAsync(requestedFile.DownloadUrl))
{
return File(await httpResponseMessage.Content.ReadAsStreamAsync(), "application/zip", "largefile.zip");
}
}
Edit:
Solution after some trial and error was remocing all using statements and letting the FileStreamResult close the stream on its own. So I ended up with:
var client = new HttpClient();
var result = await client.GetAsync(requestedFile.DownloadUrl);
var stream = await result.Content.ReadAsStreamAsync();
return new FileStreamResult(stream, "application/zip")
{
FileDownloadName = "largefile.zip"
};
One of the overloads for File is a Stream. Just get that URL as a Stream or read the response body as a stream and immediately return that in the overload:
var client = new System.Net.Http.HttpClient();
var result = await client.GetAsync(requestedFile.DownloadUrl);
var stream = await result.Content.ReadAsStreamAsync();
return File(stream,"application/pdf", "Invoice.pdf");
Note: this will fail if you wrap the Stream in a using block as the FileResult already closes the Stream.
For Export Excel
var client = new System.Net.Http.HttpClient();
var comp = client.GetAsync($"RewardEmployee/ExportExcelCalculate?rewardConfigId={id}").Result;
`var stream = await result.Content.ReadAsStreamAsync();
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"ExportExcelCalculateRewardEmployee.xlsx");

How can I create headers for a text file and upload it with httpClient?

My text file is saved on my hard disk and I want to upload it in Visual Studio to this file management service: https://learn.microsoft.com/en-us/gaming/playfab/features/data/content-delivery-network/quickstart#fetching-assets
Before uploading, I want to create the file headers, because I want to add a version number of the file to the headers. For example, I want to add "1" to the headers, if it is the first version. How can I do that?
After that, I want to upload the text file. But I don't know how to upload the file with httpClient. How can I upload the file?
I have tried it with this code, but it's not working and I don't know what I'm doing wrong. What is wrong?
private async Task UpoadNewContent()
{
var result = await PlayFabAdminAPI.GetContentUploadUrlAsync(new GetContentUploadUrlRequest()
{
Key = "Levelfiles/Level2.txt",
ContentType = "binary/octet-stream"
});
if (result.Error != null)
{
Console.WriteLine("Error.");
}
else
{
Uri webService = new Uri(result.Result.URL + "Levelfiles/" + "Level2.txt");
await UploadFileAsync(webService, "/Users/myname/TESTFOLDER/Level2.txt");
}
}
async Task UploadFileAsync(Uri uri, string filename)
{
using (var stream = File.OpenRead(filename))
{
var client = new HttpClient();
var response = await client.PostAsync(uri, new StreamContent(stream));
response.EnsureSuccessStatusCode();
}
}
I get this response:

Get upload progress from MultipartFormDataContent and StreamContent

Consider this small code below:
var client = new HttpClient();
var multiForm = new MultipartFormDataContent();
var str = new StreamContent(File.OpenRead("movie.mp4"));
multiForm.Add(str, "to_upload", "1.mp4");
var response = await client.PostAsync("https://example.com/upload", multiForm);
As you can see I'm using StreamContent and MultipartFormDataContent to upload a file. My question is it is possible to somehow get the upload progress from HttpClient? Or any other way to get upload progress?
You can make use of ProgressableStreamContent from here
or this answer
and a simple usage can be
var progress = new ProgressableStreamContent (
requestContent,
4096,
(sent,total) => {
Console.WriteLine ("Uploading {0}/{1}", sent, total);
});

How to download a file on the client device using Windows.Web.Http

I am working on a Windows to UWP app. A web service exists that when called (GET), returns a file. When the web service is triggered using a browser, it successfully downloads a file on the browser.
On the UWP app, I am using Windows.Web.Http to call the web service. I need to save get the file sent by the web service and save it on the device.
I currently have the following code. Not sure how to get the result from the web service and save to the file.
public async Task DownloadFile(string WebServiceURL, string PathToSave)
{
var myFilter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
myFilter.AllowUI = false;
Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient(myFilter);
Windows.Web.Http.HttpResponseMessage result = await client.GetAsync(new Uri(WebServiceURL));
using (IInputStream inputStream = await result.Content.ReadAsInputStreamAsync())
{
//not sure if this is correct and if it is, how to save this to a file
}
}
Using System.Web.Http, I am able to easily do this using the following:
Stream stream = result.Content.ReadAsStreamAsync().Result;
var fileStream = File.Create(PathToSave);
await stream.CopyToAsync(fileStream);
fileStream.Dispose();
stream.Dispose();
However, using Windows.Web.Http, I am not sure how I can do this. Please help!
this what you looking for?
like this?
var myFilter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
myFilter.AllowUI = false;
Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient(myFilter);
Windows.Web.Http.HttpResponseMessage result = await client.GetAsync(new Uri(WebServiceURL));
//not sure if this is correct and if it is, how to save this to a file
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("filename.tmp", CreationCollisionOption.GenerateUniqueName);
using (var filestream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
await result.Content.WriteToStreamAsync(filestream);
await filestream.FlushAsync();
}

Downloading image from url doesn't always save the entire image (Winrt)

I'm using the following code to download an image from a url
HttpClient client = new HttpClient();
var stream = await client.GetStreamAsync(new Uri("<your url>"));
var file = await KnownFolders.PictureLibrary.CreateFileAsync("myfile.png");
using (var targetStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
using (stream)
await stream.CopyToAsync(targetStream.AsStreamForWrite());
}
several users have reported that it doesn't always download the entire image. That they sometimes get partial images and the rest is just garbage.
Is there any reason for this?
Thanks!
I would suggest trying the WebClient class with the DownloadData or DownloadDataAsync method.
File.WriteAllBytes("myfile.png",
new WebClient().DownloadData("<your url>"));
edit If the stream is giving you trouble you could use the byte array response instead. Your "using" statement with async code inside may be causing it to dispose early, perhaps?
var httpClient = new HttpClient();
var data = await httpClient.GetByteArrayAsync(new Uri("<Your URI>"));
var file = await KnownFolders.PictureLibrary.CreateFileAsync("myfile.png");
var targetStream = await file.OpenAsync(FileAccessMode.ReadWrite)
await targetStream.AsStreamForWrite().WriteAsync(data, 0, data.Length);
targetStream.FlushAsync().Wait();
targetStream.Close();
BackgroundDownloader is the easiest way to download a file.
using Windows.Storage;
public async Task DownloadPhoto(Uri uri)
{
var folder = ApplicationData.Current.LocalFolder;
var photoFile = await folder.CreateFileAsync("photo.jpg", CreationCollisionOption.ReplaceExisting);
var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
var dl = downloader.CreateDownload(uri, photoFile);
await dl.StartAsync();
}
If your using HttpClient then if your image is larger than 64K it will error out. You will have to set the httpClient.MaxResponseContentBufferSize to something larger.
See the MSDN Quick Start where they set the max-buffer-size to 256K.
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/JJ152726(v=win.10).aspx
Personally though, I use the BackgroundDownloader.

Categories

Resources