Writing to a file in Windows Phone - c#

I am having trouble creating an IO stream.
I found the example below but for some odd reason the GetResourceStream is not an available in the Application class. Am I missing a reference to some API?
var resource = Application.GetResourceStream(new Uri(#"/YOURASSEMBLYNAME;component/Stations.txt", UriKind.Relative));
StreamReader streamReader = new StreamReader(resource.Stream);
string x = streamReader.ReadToEnd();

If you need to read a String from your file (as I see in your example), you can use:
StorageFile textFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///YOUR FILE PATH"));
String text = await FileIO.ReadTextAsync(textFile );
You can use the methods inside the FileIO class to write to the file as well, both from a text and from a binary buffer.
If you really want to use a buffer stream, you can get it with:
IRandomAccessStream accessStream = await textFile.OpenAsync(FileAccessMode.ReadWrite);

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");

How to get the stream for a Multipart file in webapi upload?

I need to upload a file using Stream (Azure Blobstorage), and just cannot find out how to get the stream from the object itself. See code below.
I'm new to the WebAPI and have used some examples. I'm getting the files and filedata, but it's not correct type for my methods to upload it. Therefore, I need to get or convert it into a normal Stream, which seems a bit hard at the moment :)
I know I need to use ReadAsStreamAsync().Result in some way, but it crashes in the foreach loop since I'm getting two provider.Contents (first one seems right, second one does not).
[System.Web.Http.HttpPost]
public async Task<HttpResponseMessage> Upload()
{
if (!Request.Content.IsMimeMultipartContent())
{
this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
var provider = GetMultipartProvider();
var result = await Request.Content.ReadAsMultipartAsync(provider);
// On upload, files are given a generic name like "BodyPart_26d6abe1-3ae1-416a-9429-b35f15e6e5d5"
// so this is how you can get the original file name
var originalFileName = GetDeserializedFileName(result.FileData.First());
// uploadedFileInfo object will give you some additional stuff like file length,
// creation time, directory name, a few filesystem methods etc..
var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
// Remove this line as well as GetFormData method if you're not
// sending any form data with your upload request
var fileUploadObj = GetFormData<UploadDataModel>(result);
Stream filestream = null;
using (Stream stream = new MemoryStream())
{
foreach (HttpContent content in provider.Contents)
{
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, content.ReadAsStreamAsync().Result);
stream.Position = 0;
filestream = stream;
}
}
var storage = new StorageServices();
storage.UploadBlob(filestream, originalFileName);**strong text**
private MultipartFormDataStreamProvider GetMultipartProvider()
{
var uploadFolder = "~/App_Data/Tmp/FileUploads"; // you could put this to web.config
var root = HttpContext.Current.Server.MapPath(uploadFolder);
Directory.CreateDirectory(root);
return new MultipartFormDataStreamProvider(root);
}
This is identical to a dilemma I had a few months ago (capturing the upload stream before the MultipartStreamProvider took over and auto-magically saved the stream to a file). The recommendation was to inherit that class and override the methods ... but that didn't work in my case. :( (I wanted the functionality of both the MultipartFileStreamProvider and MultipartFormDataStreamProvider rolled into one MultipartStreamProvider, without the autosave part).
This might help; here's one written by one of the Web API developers, and this from the same developer.
Hi just wanted to post my answer so if anybody encounters the same issue they can find a solution here itself.
here
MultipartMemoryStreamProvider stream = await this.Request.Content.ReadAsMultipartAsync();
foreach (var st in stream.Contents)
{
var fileBytes = await st.ReadAsByteArrayAsync();
string base64 = Convert.ToBase64String(fileBytes);
var contentHeader = st.Headers;
string filename = contentHeader.ContentDisposition.FileName.Replace("\"", "");
string filetype = contentHeader.ContentType.MediaType;
}
I used MultipartMemoryStreamProvider and got all the details like filename and filetype from the header of content.
Hope this helps someone.

reading a file into stream in windows store App without using async/await

I want to read a file from the assets into a stream, I currently use it as the following:
public async void LoadWidthOfUnicodesData()
{
string dataFile = #"Assets\QuranData\Data_Font1.xml";
StorageFolder InstallationFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFile file = await InstallationFolder.GetFileAsync(dataFile);
Stream readStream = await file.OpenStreamForReadAsync();
DataContractSerializer ser = new DataContractSerializer(typeof(List<UniCodeWidth>));
WidthOfUnicodes = (List<UniCodeWidth>)ser.ReadObject(readStream);
for (int i = 0; i < WidthOfUnicodes.Count; i++)
{
WidthOfUnicodesDict.Add(WidthOfUnicodes[i].UniCode, WidthOfUnicodes[i].Width);
}
}
The only problem with that, is that part is in my viewmodel, and as it's a non-blocking operation, when the VM initializes with the View as its DataContext, the constructor does what it's supposed to do to fill the view but I always get an exception at using the WidthOfUnicodesDict because it's not yet filled with the data.
What I want to do, is either make the reading to stream a synchronous method (without using async/await) which so far I don't know how to do it on windows store. or somehow make the VM constructor waits till this operation finishes and notifies it's done.
You can fetch a file without async/await semantics like this:
var file = Package.Current.InstalledLocation.GetFileAsync(Folder)
.GetAwaiter()
.GetResult();
I don't know how to get a stream, but you can get an IBuffer or read it as text, using FileIO:
string content = FileIO.ReadTextAsync(file).GetAwaiter().GetResult();
IList lines = FileIO.ReadLinesAsync(file).GetAwaiter().GetResult();
IBuffer buffer = FileIO.ReadBufferAsync(file).GetAwaiter().GetResult();
I've done this before and it doesn't cause any deadlocks.

How do I get the name of a file generated with a stream in C#?

I'm building a Windows 8 metro app with XAML/C#. I'm saving an .xml file my data structure with a stream, like this:
XmlSerializer serializer = new XmlSerializer(typeof(MyObjectType));
using (var stream = await App.LocalStorage.OpenStreamForWriteAsync(MyObject.Title + ".xml", Windows.Storage.CreationCollisionOption.GenerateUniqueName))
serializer.Serialize(stream, MyObject);
Where:
App.LocalStorage
Is obviously a StorageFolder objecty set to
Windows.Storage.ApplicationData.Current.LocalFolder
The GenerateUniqueName option is set in order to avoid collisions, because my objects can have the same title. Now, I need to get the file name my stream generated, how can I get it?
Thank you
Try creating the file first.
var sourceFileName = MyObject.Title + ".xml";
StorageFile storageFile = await App.LocalStorage.CreateFileAsync(sourceFileName, Windows.Storage.CreationCollisionOption.GenerateUniqueName);
using (var stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
serializer.Serialize(stream, MyObject);
}
The OpenStreamForWriteAsync method does not seem to give you any easy way to access this information. You could switch to accessing it another way:
StorageFile file = await App.LocalStorage.CreateFileAsync(...);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
// do stuff, file name is at file.Name

System.Unauthorizedaccesexception while reading and writing an xml using Windows 8 xaml C#

I am working on windows 8 xaml C# apps, I am trying to read a song xml and append new node to it. The code is:
StorageFolder sf;
sf = KnownFolders.MusicLibrary;
StorageFile file = await sf.GetFileAsync(strSongName);
var item = await file.OpenAsync(FileAccessMode.Read);
IRandomAccessStream raStream;
IOutputStream outputStream;
DataWriter writer;
var lc = ApplicationData.Current.LocalFolder;
var infolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(infolder.Path);
StorageFile file1 = await folder.GetFileAsync("songxml.xml");
var filetest = await file1.OpenAsync(FileAccessMode.Read);
Stream inStream = filetest.AsStreamForRead();
XDocument xdoc = XDocument.Load(inStream);
string content = xdoc.ToString();
raStream = await file1.OpenAsync(FileAccessMode.ReadWriteUnsafe);
outputStream = raStream.GetOutputStreamAt(0);
writer = new DataWriter(outputStream);
StringBuilder outputText = new StringBuilder();
outputText.Append(content.ToString());
I get a System.Unauthorizedaccessexception while running this code
My psychic debugging powers tell me you need to mention in your capabilities that you'll be accessing the Music known folder, and that you haven't done that yet.
Am I right?
I have...well actually had the same problem. Given the date of your last comment, I guess you've figured it out by now. Nevertheless, maybe there will be others that visit this thread, so...
I guess you should make sure that you've added the extensions you expect to Declarations->Supported Declarations->File Type Associations.
Maybe this limitation is not there, when using the Music Library, but for the Documents Library (make case), this is exactly the case.
Edit: Make sure you backup the contents of the LocalState folder, because every change to the application manifest results in deleting your contents.
Happy coding

Categories