Getting a Stream from a resource file / content - c#

Is this the correct/only way of getting a Stream from a resource file?
Uri uri = new Uri(fullPath);
StorageFile storageFile =
await Windows.Storage.StorageFile.
GetFileFromApplicationUriAsync(uri);
IRandomAccessStreamWithContentType randomAccessStream =
await storageFile.OpenReadAsync();
IInputStream resourceStream = (IInputStream)
randomAccessStream.GetInputStreamAt(0);
All my other sources (http and local storage) return a Stream object, and it is painful to have to if-else code that uses one or the other.
I've also tried to just create a MemoryStream out of it, but I can't even find a way to get the bytes out... Please help.
uint size = (uint)randomAccessStream.Size;
IBuffer buffer = new Windows.Storage.Streams.Buffer(size);
await randomAccessStream.ReadAsync(buffer, size,
InputStreamOptions.None);
Stream stream = new MemoryStream(buffer); // error takes byte[] not IBuffer
IInputStream.ReadAsync() when reading from resource:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.iinputstream.readasync.aspx
while Stream.Read() and Stream.ReadAsync() look like this:
http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx
and
http://msdn.microsoft.com/en-us/library/hh137813.aspx
Thanks

Ok I found it!
StorageFile storageFile =
await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri);
var randomAccessStream = await storageFile.OpenReadAsync();
Stream stream = randomAccessStream.AsStreamForRead();

You can also do it in one less line:
Stream stream = await storageFile.OpenStreamForReadAsync();

Related

Form Recognizer SDK, analyze with custom model, file stream issue

When I'm trying to analyze a pdf document using FileStream from a local file, everything works fine.
But when I use a IFormFile and use method OpenReadStream() and pass that stream to the Analyze method for form analyzer, i get an exception. I also tried creating a new stream out of the IFromFile stream and that did not work either.
Any help will be much appreciated. Thank you
Working code:
using var stream = new FileStream("D:\\somefile.pdf", FileMode.Open);
var result = await _formRecognizerClient.AnalyzeWithCustomModelAsync(modelId, fileStream, "application/pdf");
Code I am trying to make work:
using var stream = file.OpenReadStream(); // file is an IFormFile
var result = await _formRecognizerClient.AnalyzeWithCustomModelAsync(modelId, stream , file.ContentType);
I have a solution for now, its not elegant but it works. I am of course very much looking for something better if anyone can help.
For now, I am creating a file, saving it and creating a FileStream out of it. Also works in docker as I'm testing using docker-compose
var iFormFileStream = file.OpenReadStream();
var stream = File.Create(string.Format("tempfilename.pdf", File.));
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(stream);
stream.Close();
using var fileStream = new FileStream("tempfilename.pdf", FileMode.Open);
var result = await _formRecognizerClient.AnalyzeWithCustomModelAsync(modelId, fileStream, "application/pdf");

UWP - How to Save a Contact Thumbnail to Local Storage?

i want some help to get the thumbnail image of a Contact and save it to Local Storage, i successfully got the contact Thumbnail but i can't get the actual image from the stream, this is my Code:
var contactStore = await ContactManager.RequestStoreAsync();
var contacts = await contactStore.FindContactsAsync();
var myContact = contacts[0]; //I am sure that this Contact has a Thumbnail
var stream = await myContact.Thumbnail.OpenReadAsync();
byte[] buffer = new byte[stream.Size];
var readBuffer = await stream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("image.jpg", CreationCollisionOption.ReplaceExisting);
var fileStream = await file.OpenStreamForWriteAsync();
await fileStream.WriteAsync(readBuffer.ToArray(), 0, (int)readBuffer.Length);
this code creates an empty image in the local storage, any help ?
thanks for your time
The problem here is that you missed Stream.Flush method to flush the buffer to the underlying stream. You can add fileStream.Flush(); after fileStream.WriteAsync method to fix your issue.
Besides this, we also need to call Stream.Dispose Method to releases the resources used by the Stream when we finish using it. And this method disposes the stream, by writing any changes to the backing store and closing the stream to release resources. So we can just use fileStream.Dispose() after fileStream.WriteAsync method.
A recommend way to call the Dispose method is using the C# using statement like following:
var contactStore = await ContactManager.RequestStoreAsync();
var contacts = await contactStore.FindContactsAsync();
var myContact = contacts[0]; //I am sure that this Contact has a Thumbnail
using (var stream = await myContact.Thumbnail.OpenReadAsync())
{
byte[] buffer = new byte[stream.Size];
var readBuffer = await stream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("image.jpg", CreationCollisionOption.ReplaceExisting);
using (var fileStream = await file.OpenStreamForWriteAsync())
{
await fileStream.WriteAsync(readBuffer.ToArray(), 0, (int)readBuffer.Length);
}
}
I believe you may have to call stream.Dispose() after you read from it or else initialize the stream with a using directive: using (var outputStream = stream.GetOutputStreamAt(0))
The following link might be useful:
https://msdn.microsoft.com/en-us/windows/uwp/files/quickstart-reading-and-writing-files?f=255&MSPPError=-2147217396

Errors converting form file to memory stream

I am trying to upload a file and save into Azure Blob storage.
The file is injected as a FormFile.
The problem is that, there are errors when I convert the FormFile to a memory stream. The stream then uploads to Azure but with no data contained.
public async Task<IActionResult> Create([Bind("EndorsementId,FileName,ProviderId,Title")] Endorsement endorsement, IFormFile formFile)
{
if (ModelState.IsValid)
{
...
var data = new MemoryStream();
formFile.CopyTo(data);
var buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
UploadToAzure(data);
...
The errors are on the ReadTimeOut and WriteTimeOut properties of the memory stream. They say 'data.ReadTimeout' threw an exception of type 'System.InvalidOperationException' and 'data.WriteTimeout' threw an exception of type 'System.InvalidOperationException' respectively.
Here is how I injected the FormFile. There seems to be very little information on this.
http://www.mikesdotnetting.com/article/288/uploading-files-with-asp-net-core-1-0-mvc
Thanks in advance.
IFormFile has CopyToAsync method for this purpose. You can just do something like below:
using (var outputStream = await blobReference.OpenWriteAsync())
{
await formFile.CopyToAsync(outputStream, cancellationToken);
}
The offset of the MemoryStream is still at the end of the file after you fill in the data. You can either reset the position:
var data = new MemoryStream();
formFile.CopyTo(data);
// At this point, the Offset is at the end of the MemoryStream
// Either do this to seek to the beginning
data.Seek(0, SeekOrigin.Begin);
var buf = new byte[data.Length];
data.Read(buf, 0, buf.Length);
UploadToAzure(data);
Or, rather than doing all of the work yourself, you can make MemoryStream just copy the data out for you to a byte[] array, by doing this after the CopyTo() call:
// Or, save yourself some work and just do this
// to make MemoryStream do the work for you
UploadToAzure(data.ToArray());
You can also upload content of IFormFile to Azure Blob Storage like this:
using (var stream = formFile.OpenReadStream())
{
var blobServiceClient = new BlobServiceClient(azureBlobConnectionString);
var containerClient = blobServiceClient.GetBlobContainerClient("containerName");
var blobClient = containerClient.GetBlobClient("filename");
await blobClient.UploadAsync(stream);
}

Set stream for MediaElement from Http request

I have a code for recording some music/video file from online stream (video stream or radio).
How can I modify it for setting the SetSource property to my MediaElement (from IBuffer or Bytes[],... for example)?
(I cannot use the variant like this:
mediaElement1.Source = new Uri(urlLinkToOnlineStream);
mediaElement1.Play();
)
I need to set SetSource directly from already opened stream (I need write to file and record the same bytes[] from stream in the same moment or with a small pause).
HttpClientHandler aHandler = new HttpClientHandler();
aHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
HttpClient aClient = new HttpClient(aHandler);
aClient.DefaultRequestHeaders.ExpectContinue = false;
HttpResponseMessage response = await aClient.GetAsync(urlLinkToOnlineStream, HttpCompletionOption.ResponseHeadersRead);
var destinationFile = await KnownFolders.MusicLibrary.CreateFileAsync(#"recorded.mp3", CreationCollisionOption.ReplaceExisting);
var fileStream = await destinationFile.OpenAsync(FileAccessMode.ReadWrite);
Stream stream = await response.Content.ReadAsStreamAsync();
IInputStream inputStream = stream.AsInputStream();
ulong totalBytesRead = 0;
while (true)
{
// Read from the web.
IBuffer buffer = new Windows.Storage.Streams.Buffer(1024);
buffer = await inputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None);
if (buffer.Length == 0)
{
break;
}
totalBytesRead += buffer.Length;
await fileStream.WriteAsync(buffer);
}
inputStream.Dispose();
fs.Dispose();
Are you developing the Universal Windows Platform App or Windows Phone 8.1 App? The UWP supports the media stream protocol like HTTP Live Stream. You can assign the URL to the media element directly.
UWP:
media.Source = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
For Windows Phone 8.1, you can use the open source stream media library.
For example: Windows Phone Streaming Media
I know this is old, however I have a working example for a single audio file that can be adapted for a stream.
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
HttpClient hc = new HttpClient();
HttpResponseMessage msg = await hc.GetAsync(urlLinkToOnlineStream);
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.
I'm not entirely sure how you intend to do the buffering, but you if you call Dispose() on the stream (in my example) playback will fail. It will also start playing the new chunk of data if you call SetSource before current chunk has finished.

How to get a stream of an in memory string?

I have a string of data, I want to have a stream of it without saving it to storage as a file and then getting an stream of it. then I will send this stream to SkyDrive. anyway.
await client.UploadAsync(folderId, filename, stream, OverwriteOption.Overwrite);
Is there anyway to get a stream of an in-memory string value, without saving it to storage first?
You can write it into a MemoryStream:
using(var stream = new MemoryStream())
{
var writer = new StreamWriter(stream);
writer.Write(yourString);
writer.Flush();
stream.Position = 0;
await client.UploadAsync(folderId, filename, stream, OverwriteOption.Overwrite);
}
Sure, use the MemoryStream class. You could load it like this for example:
var stream = new MemoryStream(Encoding.ASCII.GetBytes("Here is my string."));
or, you can just Write new data to it like this:
var myString = "Hello, World!";
stream.Write(Encoding.ASCII.GetBytes(myString), 0, myString.Length);
You could of course use a different encoding if you needed to, say UTF8 for example.

Categories