Download and save a picture from a url Universal windows app - c#

I am using the below code to downlaod the picture form a remote url and save to Local storage folder
try
{
var rootFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync( "MyAppName\\CoverPics", CreationCollisionOption.OpenIfExists);
var coverpic_file = await rootFolder.CreateFileAsync(filename, CreationCollisionOption.FailIfExists);
try
{
var httpWebRequest = HttpWebRequest.CreateHttp(coverUrl);
HttpWebResponse response = (HttpWebResponse)await httpWebRequest.GetResponseAsync();
Stream resStream = response.GetResponseStream();
using (var stream = await coverpic_file.OpenAsync(FileAccessMode.ReadWrite))
{
await resStream.CopyToAsync(stream.AsStreamForWrite());
}
response.Dispose();
}
catch //any exceptions happend while saving the picture
{
saved = false;
}
}
catch
{
//https://msdn.microsoft.com/en-us/library/windows/apps/br227250.aspx
//Raise an exception if file already present
saved = true;
}
This code is working for me in most of the cases , but i noticed that for few pictures the image is not downloading completely.
I am callling this function in an async block for more tahn 100 images in a single go inside the foreach loop and in the end few of them are failed downloads
[ Either i can see some invalid file is getting created
or part of image only in downloading and rest of the area i can see a black colour block [ looks like image is corrupted].
Size of all images is less than 1 MB only
Can some one help me to optimize this code or point out the mistake in code so i can able to download all the images completely

I am not seeing any error in my code. But after trying some different ways of downloading and saving a file my code looks like this and
try
{
HttpClient client = new HttpClient(); // Create HttpClient
byte[] buffer = await client.GetByteArrayAsync(coverUrl); // Download file
using (Stream stream = await coverpic_file.OpenStreamForWriteAsync())
stream.Write(buffer, 0, buffer.Length); // Save
}
catch
{
saved = false;
}
And this code is working fine without causing any issues All images are downloading completely and no more issues of black block on images.
If any one can points out the difference with my first code will be really helpful to understood the reason for error

Have you tried using new Windows.Web.Http.HttpClient instead of HttpWebRequest?
Also take a look this SO question :
How do I use the new HttpClient from Windows.Web.Http to download an image?
If you not familiar with HttpClient, I sugest to watch CH9 presentation :
https://channel9.msdn.com/Events/Build/2013/4-092

I tried your download and experienced the same issues.
var myFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("MyFolderPath", CreationCollisionOption.OpenIfExists);
var myFile = await myFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(new Uri(URL), myFile);
await download.StartAsync();

Related

Stream video from RavenDB through ASP.Net MVC

I'm trying to stream a Video, that is saved as an attachment in a Ravendb-Database, through an ASP.NET MVC 5 Action to a WebBrowser. It is working with the following Code, but the Video gets fully downloaded before the Video starts. I don't get what I'm doing wrong.
I found some ways to do Streaming in MVC, but they seem to expect a Seekable Stream - but the stream I receive from Ravendb is not seekable; it even does not provide a length. So the only way of doing it would be to copy the ravendb-stream to a memorystream and provide a PartialContent or similar from there.
Does anybody have a better solution? I cannot be the only one that wants to stream a Video from a database without loading the full Video into Memory before sending it.
I'm fetching the attachment from ravendb like this:
public async Task<System.IO.Stream> GetAttachmentAsync(IAttachmentPossible attachedObject, string key)
{
using (var ds = InitDatabase())
{
using (var session = ds.OpenAsyncSession())
{
try
{
var result = await session.Advanced.Attachments.GetAsync(attachedObject.Id, key);
return result.Stream;
}
catch (Exception ex)
{
return null;
}
}
}
}
After that I send the stream to the browser like this:
var file = await _database.GetAttachmentAsync(entry, attachmentId);
HttpResponseMessage msg = new HttpResponseMessage(HttpStatusCode.OK);
msg.Content = new StreamContent(file);
msg.Content.Headers.ContentType = new MediaTypeHeaderValue("video/mp4");
return msg;
Any ideas? Thank you very much!
I think that it is correct to copy the stream into a memory stream. With the answer you linked (https://stackoverflow.com/a/39247028/10291808) you can do streaming.
Maybe could be an idea to think about the multiple calls that will done to retrieve the file from the db (maybe you could cache the file for a limited time to improve performance).

HttpPostedFileBase Stream Upload to AWS SDK Bucket has no Data

I'm testing how to upload to AWS using SDK with a sample .txt file from a web app. The file uploads to the Bucket, but the downloaded file from the bucket is just an empty Notepad document without the text from the original uploaded file. I'm new to working with streams, so I'm not sure what could be wrong here. Does anyone see why the data wouldn't be sent in the transfer request? Thanks in advance!
using (var client = new AmazonS3Client(Amazon.RegionEndpoint.USWest1))
{
//Save File to Bucket
using (FileStream txtFileStream = (FileStream)UploadedHttpFileBase.InputStream)
{
try
{
TransferUtility fileTransferUtility = new TransferUtility();
fileTransferUtility.Upload(txtFileStream, bucketLocation,
UploadedHttpFileBase.FileName);
}
catch (Exception e)
{
e.Message.ToString();
}
}
}
EDIT:
Both TransferUtility and PutObjectRequest/PutObjectResponse/AmazonS3Client.PutObject saved a blank text file. Then, after having some trouble instantiating a new FileStream, a MemoryStream used after resetting the starting position to zero still saved a blank text file. Any ideas?
New Code:
using (var client = new AmazonS3Client(Amazon.RegionEndpoint.USWest1))
{
Stream saveableStream = new MemoryStream();
using (Stream source = (Stream)UploadedHttpFileBase.InputStream)
{
source.Position = 0;
source.CopyTo(saveableStream);
}
//Save File to Bucket
try
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = bucketLocation,
Key = UploadedHttpFileBase.FileName,
InputStream = saveableStream
};
PutObjectResponse response = client.PutObject(request);
}
catch (Exception e)
{
e.Message.ToString();
}
}
Most probably that TransferUtility doesn't work good with temporary upload files. Try to copy your input stream somewhere (e.g. into other not-so-temporary file, or even MemoryStream if you're sure it would not give you OutOfMemory at some point). Another thing is to get rid of TransferUtility and use low-level AmazonS3Client.PutObject with which you get finer control over Stream lifetime (do not forget that you'll need to implement some retrying as S3 API is prone to returning random temporary errors).
The answer had something to do with nesting, which is still a little beyond my understanding, and not because the code posted here was inherently wrong. This code came after an initial StreamReader which checked the first line of the text file to determine whether or not to save the file. After moving the code out from the while loop doing the ReadLines, the upload worked. Everything works as it's supposed to now that the validation is reorganized so that there's no need for the nested Stream or MemoryStream.

SoundCloud Stream_url doesnt work on Raspberry Pi

I have been discussing this topic on another forum and no one could actually help, let's see if someone here can.
I Have a Problem with the URI you get from the Soundcloud Api to play a song. On my dekstop this Command:
mediaelement.Source = new Uri("https://api.soundcloud.com/tracks/218090824/stream?client_id=YOUR_CLIENT_ID");
mediaelement.Play();
works just fine, on the PI it doesn't at all, no clue why.
I have a workaround for now which looks like this:
Uri turi = new Uri("https://api.soundcloud.com/tracks/218090824/stream?client_id=YOUR_CLIENT_ID");
IRandomAccessStreamReference rsr = RandomAccessStreamReference.CreateFromUri(turi);
PBar.Visibility = Windows.UI.Xaml.Visibility.Visible;
StorageFile file1 = await StorageFile.CreateStreamedFileFromUriAsync("test mp3", turi, rsr);
IRandomAccessStream stream = await file1.OpenReadAsync();
PBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
mediaElement.PosterSource = img;
mediaElement.SetSource(stream, "audio/mp3");
mediaElement.Play();
The Problem here is that the files are being downloaded before they are played, this is not a problem if the songfile is <10 mb but with mixtapes >100 mb this takes a long time. So Is it somehow possible to get an IRandomAccessStream from the URI which can be played while being downloaded?
This Solution:
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync("https://api.soundcloud.com/tracks/218090824/stream?client_id=YOUR_CLIENT_ID", HttpCompletionOption.ResponseHeadersRead);
HttpResponseMessage rs = await httpClient.GetAsync(response.RequestMessage.RequestUri, HttpCompletionOption.ResponseHeadersRead);
Stream stream = await rs.Content.ReadAsStreamAsync();
IRandomAccessStream content = stream.AsRandomAccessStream();
mediaElement.SetSource(content, "audio/mpeg");
doesn't work because I get an error when i want to convert the Stream to IRandomAccessStream which says: ""Cannot use the specified Stream as a Windows Runtime IRandomAccessStream because this Stream does not support seeking."
Issue has been resolved with the latest Windows IOT Update.

The component cannot be found. (Exception from HRESULT: 0x88982F50)

The above exception occurs at line await bitmapImage.SetSourceAsync(fileStream); whenever I tried to retrieve image from local file.
This is the method I'm using for storing and retrieving the image file.
public async Task<BitmapImage> RetrieveImageFromFile(String fileName)
{
try
{
StorageFile localFile = await _storageFolder.GetFileAsync(fileName + "Img");
BitmapImage bitmapImage = new BitmapImage();
using (IRandomAccessStream fileStream = await localFile.OpenAsync(FileAccessMode.Read))
{
await bitmapImage.SetSourceAsync(fileStream);
}
return bitmapImage;
}
catch(Exception e)
{
return null;
}
}
public async void WriteImageToFile(string fileName, IRandomAccessStreamWithContentType stream )
{
StorageFile file = await _storageFolder.CreateFileAsync(fileName + "Img", CreationCollisionOption.ReplaceExisting);
Stream streamToSave = stream.AsStreamForWrite();
using (Stream fileStram = await file.OpenStreamForWriteAsync())
{
streamToSave.CopyTo(fileStram);
}
}
The input stream for the WriteImageToFile method is retrieved from contact.Thumbnail.OpenReadAsync() method
Any help ?
Just turning my comment into an answer since it's been helping people:
The 0x88982f50 error is generally related to a failure to read/decode an image file correctly. Verify your file is formatted properly. Google 88982f50 to see dozens of potentially related fixes, all relating to image file I/O. I never did find a definitive source for the error but this turned out to be my problem as well... Bad file.
Late answer but might save someone else from spending hours hunting this down...
Error code 0x88982f50 is WINCODEC_ERR_COMPONENTNOTFOUND, and it's the Windows Imaging Component's way of saying it can't decode an image file.
Most likely the file is corrupted, or the version of WIC installed in Windows doesn't include a codec needed to decode it.
Microsoft provides zero information about it.

Download and Save image in Pictures Library through Windows 8 Metro XAML App

I am trying to develop a simple Windows 8 Metro app which simply downloads an image file from a given URL (say http://sample.com/foo.jpg) and then save it to Pictures Library.
I have an image control in the UI to display the downloaded image.
I'm also facing difficulty in setting the image source for the image control to the newly downloaded image (actually I'm not even able to download it).
Also, is it possible to store the image file in a particular folder in the Pictures library (if it doesn't exist, then the app should create it)?
I'm really stuck here.
Please help me.
Here's some rough code that I believe accomplishes what you want. It assumes you have two image controls (Image1 and Image2) and that you have the Pictures Library capability checked in the manifest. Take a look at the XAML images sample as well
Uri uri = new Uri("http://www.picsimages.net/photo/lebron-james/lebron-james_1312647633.jpg");
var fileName = Guid.NewGuid().ToString() + ".jpg";
// download pic
var bitmapImage = new BitmapImage();
var httpClient = new HttpClient();
var httpResponse = await httpClient.GetAsync(uri);
byte[] b = await httpResponse.Content.ReadAsByteArrayAsync();
// create a new in memory stream and datawriter
using (var stream = new InMemoryRandomAccessStream())
{
using (DataWriter dw = new DataWriter(stream))
{
// write the raw bytes and store
dw.WriteBytes(b);
await dw.StoreAsync();
// set the image source
stream.Seek(0);
bitmapImage.SetSource(stream);
// set image in first control
Image1.Source = bitmapImage;
// write to pictures library
var storageFile = await KnownFolders.PicturesLibrary.CreateFileAsync(
fileName,
CreationCollisionOption.ReplaceExisting);
using (var storageStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
await RandomAccessStream.CopyAndCloseAsync(stream.GetInputStreamAt(0), storageStream.GetOutputStreamAt(0));
}
}
}
// read from pictures library
var pictureFile = await KnownFolders.PicturesLibrary.GetFileAsync(fileName);
using ( var pictureStream = await pictureFile.OpenAsync(FileAccessMode.Read) )
{
bitmapImage.SetSource(pictureStream);
}
Image2.Source = bitmapImage;
}

Categories

Resources