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.
Related
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");
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);
});
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();
}
I have search all over SO and on google.
Im trying to find a example of how I can stream internet radio (mp3) from a Windows Store App.
All the examples I found are small pieces of code that doesn't work.
Can someone explain or show code on how exactly I should do.
I have been trying mediaelement and some others.
I tried this
public async void Play()
{
Uri bla = new Uri(string.Format("http://live-icy.gss.dr.dk/A/A04H.mp3.m3u"), UriKind.Absolute);
var uriStreamReference = RandomAccessStreamReference.CreateFromUri(bla);
var uriStream = await uriStreamReference.OpenReadAsync();
nm.SetSource(uriStream, "audio/mp4");
}
Hope someone can help
I know this is old, however I have a working example.
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
Uri uri = new Uri("http://live-icy.gss.dr.dk/A/A04H.mp3.m3u");
HttpClient hc = new HttpClient();
HttpResponseMessage msg = await hc.GetAsync(uri);
await RandomAccessStream.CopyAsync(await msg.Content.ReadAsInputStreamAsync(), stream);
stream.Seek(0);
myMediaElement.SetSource(stream, msg.Content.Headers.ContentType.ToString());
You must remember to call Dispose() on your InMemoryRandomAccessStream and HttpClient when you are sure you have finished with them. Otherwise you will most likely end up with a memory leak.
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);
}