Unable to delete a file with DeleteAsync - c#

I'm working in VS2012, WinRT and C#.
I'm trying to delete some files after decompressing them. I'm getting an "Access is denied" error. If I stop the app and re-start it the same code works fine so it appears there is a handle still attached.
If I don't call the unZipFile method, I can delete the files.
Is there a definitive way to release a file? I've set it to null (file = null;) before the call to delete.
Here's the block of code that calls the unzip method:
StorageFile file = await CreateOutputFile(fileName, path);
MemoryStream theMemStream = new MemoryStream();
theMemStream.Write(bytes, 0, bytes.Length);
await FileIO.WriteBytesAsync(file, bytes);
await theMemStream.FlushAsync();
theMemStream.Dispose();
var result = await unZipFile(file, path);
file = null;
Here's the unZipFile method:
private async Task<string> unZipFile(StorageFile file, string path)
{
StorageFolder sf = await GetOutputFolder(path);
using (var zipStream = await file.OpenStreamForReadAsync())
{
using (MemoryStream zipMemoryStream = new MemoryStream((int)zipStream.Length))
{
await zipStream.CopyToAsync(zipMemoryStream);
try
{
var archive = SharpCompress.Archive.ArchiveFactory.Open(file.Path);
foreach (var entry in archive.Entries)
{
entry.WriteTo(zipMemoryStream);
Stream fileData = entry.OpenEntryStream();
StorageFile outputFile = await sf.CreateFileAsync(entry.FilePath, CreationCollisionOption.ReplaceExisting);
using (Stream outputFileStream = await outputFile.OpenStreamForWriteAsync())
{
await fileData.CopyToAsync(outputFileStream);
await outputFileStream.FlushAsync();
outputFileStream.Dispose();
}
}
archive = null;
}
catch (Exception ex)
{
throw new IOException("Error writing decompressed output file: " + ex.Message);
}
await zipStream.FlushAsync();
zipStream.Dispose();
await zipMemoryStream.FlushAsync();
zipMemoryStream.Dispose();
}
}
return "success";
}
Here's the delete method. This is called for each file after decompression:
private async Task<string> deleteFile(string path, string filename)
{
StorageFolder folder = await GetOutputFolder(path);
var files = await folder.GetFilesAsync();
foreach (StorageFile file in files)
{
try
{
if (file != null)
{
if (file.Name == filename)
await file.DeleteAsync();
}
}
catch (Exception ex)
{
return ex.Message;
}
}
return "success";
}

On what file do you get the exception, the extracted files or the zip archive itself?
If the latter is the case, ArchiveFactory.Open() returns an IArchive which inherits IDisposable, so you should wrap var archive = SharpCompress.Archive.ArchiveFactory.Open(file.Path); in a using block so it gets disposed after use.

Related

System.OutOfMemoryException when reading content of a file in a Web API

I want to send the content of file as memory stream to S3 bucket via Amazon Firehose. below is my attempt which works fine for small files, but I have a file of 1 GB and I am getting {"Exception of type 'System.OutOfMemoryException' was thrown."}.
My code snippet:
[HttpPost]
public async Task<bool> Upload()
{
try
{
var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
foreach (var stream in filesReadToProvider.Contents)
{
var fileBytes = await stream.ReadAsByteArrayAsync(); // THIS IS WHERE EXCEPTION COMES
using (MemoryStream memoryStream = new MemoryStream(fileBytes))
{
PutRecordRequest putRecord = new PutRecordRequest();
putRecord.DeliveryStreamName = myStreamName;
Record record = new Record();
record.Data = memoryStream;
putRecord.Record = record;
await kinesisClient.PutRecordAsync(putRecord);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return true;
}
I looked into this link OutOfMemoryExceptoin but I could not comprehend it. Please help me.
Attempt 1:
var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
foreach (var stream in filesReadToProvider.Contents)
{
var fileByte = await stream.ReadAsStreamAsync();
MemoryStream _ms = new MemoryStream();
fileByte.CopyTo(_ms); // EXCEPTION HERE
try
{
PutRecordRequest putRecord = new PutRecordRequest();
putRecord.DeliveryStreamName = myStreamName;
Record record = new Record();
record.Data = _ms;
putRecord.Record = record;
await kinesisClient.PutRecordAsync(putRecord);
}
catch (Exception ex)
{
Console.WriteLine("Failed to send record to Kinesis. Exception: {0}", ex.Message);
}
}
[HttpPost]
public async Task<bool> Upload()
{
try
{
using(var requestStream = await Request.Content.ReadAsStreamAsync())
{
PutRecordRequest putRecord = new PutRecordRequest();
putRecord.DeliveryStreamName = myStreamName;
Record record = new Record();
record.Data = requestStream ;
putRecord.Record = record;
await kinesisClient.PutRecordAsync(putRecord);
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return true;
}
This will read the data in chunks. Keep everything in the Stream so you don't keep all the bytes around in a huge array.
When reading large files, I use StreamReader's Readline() method. It works on large files as it manages file system caching internally. Can you use this method, instead? Is there a reason why you are implementing the MemoryStream class? You have a comment asking how to inject the data? Did you try using one of MemoryStream's methods???
https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream?view=netframework-4.7.2
Update:
Not sure if this is helpful since the code is substantially different from what you are using. But, yours isn't working either, so just a suggestion.
http://www.tugberkugurlu.com/archive/efficiently-streaming-large-http-responses-with-httpclient

WP 8.1 - How to save an image to Isolated Storage if know it's URL

I have the image URL.
How can I save it into Isolated Storage in WP 8.1.
Can I trigger both save it and then share it onto Facebook with only one button?
This is my code - which work well following Burak Kaan Köse's:
public async void GetImage()
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
if (folder != null)
{
StorageFile file = await folder.CreateFileAsync("imagefile", CreationCollisionOption.ReplaceExisting);
string url = imgUri[fLFl.SelectedIndex].ToString();
HttpClient client = new HttpClient();
byte[] fileContent = await client.GetByteArrayAsync(url); ; // This is where you set your content as byteArray
Stream fileStream = await file.OpenStreamForWriteAsync();
fileStream.Write(fileContent, 0, fileContent.Length);
fileStream.Flush();
fileStream.Dispose();
}
}
Don't forget to change 'imagefile' path and fileContent variable.
private async void SaveFile()
{
try
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
if(folder != null)
{
StorageFile file = await folder.CreateFileAsync("imagefile", CreationCollisionOption.ReplaceExisting);
byte[] fileContnet = null; // This is where you set your content as byteArray
Stream fileStream = await file.OpenStreamForWriteAsync();
fileStream.Write(fileContent, 0, fileContent.Length);
fileStream.Flush();
fileStream.Close();
}
}
catch (Exception ex)
{
// Some Exception handling code
}
}

Windows Phone 8.1 Writing to File Not Working

I am writing text to a file in Windows Phone 8.1 like this:
private static async Task WriteData(String fileName, String content)
{
Byte[] data = Encoding.Unicode.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}
But when I read the file, it comes back empty. I have verified that there isn't some other method overwriting it by reading from the file immediately after I write to it. Am I missing something obvious here?
Maybe you can try:
public async Task SaveStreamToFile(Stream streamToSave, string fileName, CancellationToken cancelToken)
{
Byte[] buf= Encoding.Unicode.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream fileStram = await file.OpenStreamForWriteAsync())
{
int bytesread = 0;
while ((bytesread = await streamToSave.ReadAsync(buf, 0, BUFFER_SIZE)) > 0)
{
await fileStram.WriteAsync(buf, 0, bytesread);
cancelToken.ThrowIfCancellationRequested();
}
}
}
I was having the same problem. I save 2 files, one with debug information, and one with application specific information (a list of routes).The debug information seems to work OK
StorageFolder local = ApplicationData.Current.LocalFolder;
var file = await local.CreateFileAsync "debug.txt",CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, sbDebugInformation.ToString());
but the CreateCollisionOption.ReplaceExisting seemed to be causing problems with the other information, and I ended up with this, after many alternate attempts
StorageFolder local = ApplicationData.Current.LocalFolder;
var json = new DataContractJsonSerializer(typeof(RouteList));
var file = await local.CreateFileAsync(filename,CreationCollisionOption.OpenIfExists);
MemoryStream stream = new MemoryStream();
json.WriteObject(stream, routes);
await FileIO.WriteBytesAsync(file, stream.ToArray());

Launching PDF reader on windows phone 8

I'm trying to launch pdf reader with the code below but it does not work. Can somebody help me?
private async Task<StorageFile> WriteData(string fileName, byte[] data)
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
s.Close();
}
return file;
}
private async Task<bool> OpenPdf(StorageFile file)
{
var uri = new Uri(file.Path, UriKind.RelativeOrAbsolute);
bool result = await Windows.System.Launcher.LaunchUriAsync(uri);
return result;
}
private async void FetchPdf() {
// Fetch pdf bytes to network
//....
StorageFile file = await WriteData("test.pdf", data);
if (file != null) {
bool result = await OpenPdf(file);
if (result)
Debug.WriteLine("Success");
else
Debug.WriteLine("Cannot open pdf file.");
}
}
result is always false and so launcher is not presented.
I used LaunchUriAsync because LaunchFileAsync is not implemented on Windows Phone.
LaunchUriAsync isn't supported on Windows Phone 8 per the documentation. It throws an exception if called
You can use Windows.System.Launcher.LaunchFileAsync to launch a StorageFile.
This code works for example (assming there's a file called "metro.pdf" in the project, with the Build Action set to Content, with Copy to Output Directory set to Copy if Newer).
var installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assets = await installedLocation.GetFolderAsync("Assets");
var pdf = await assets.GetFileAsync("metro.pdf");
Windows.System.Launcher.LaunchFileAsync(pdf);
Called the API and saved the byte array to file
public static async void WriteDataToIsolatedStorageFile(string fileName, byte[] data)
{
using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = storageFile.OpenFile(fileName, FileMode.Create))
{
if ((data != null) && (data.Length > 0))
{
await stream.WriteAsync(data, 0, data.Length);
}
}
}
}
opened the file in pdf reader using
private async void StartExternalPDFApp()
{
StorageFolder localFolder = await FileManager.FindDirectory(FileManager.RelativeStorageDirectoryLocalStorage);
StorageFile storageFile = await localFolder.GetFileAsync(PdfFileName);
await Windows.System.Launcher.LaunchFileAsync(storageFile);
}
localFolder is Windows.Storage.ApplicationData.Current.LocalFolder
just put the anyFile.pdf in Assets folder, and make its build action to Content, and then Just make the function Async ... and then Put "await" before Windows.System.Launcher.LaunchFileAsync(pdf);
it worked fine for me. Nice.
See this.
private async void privacyPolicy_Click(object sender, EventArgs e)
{
var installedLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assets = await installedLocation.GetFolderAsync("Assets");
var pdf = await assets.GetFileAsync("PrivacyPolicy.pdf");
await Windows.System.Launcher.LaunchFileAsync(pdf);
}

Windows Store App how to delete text from file

In a windows store app, how can I delete text from a file ? For example
If I have
StorageFile file = await roamingfolder.CreateFileAsync(filename,
CreationCollisionOption.OpenIfExists);
await FileIO.AppendTextAsync(file, temp);
How can i remove some text from this file ?
You generally read the text into a string, remove the text, and rewrite the file.
Here I get a file then I put the content to a stringbuilder then do some string operations, finally put the string back to the file using DataWriter
public static async Task UpdateTextContent(string contentItemId)
{
var storageFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync(TARGET_FOLDER);
StorageFile sf = null;
try
{
//get content of the file make sure that it exist
sf = await storageFolder.GetFileAsync(TARGET_FILE);
}
catch (Exception ex)
{
}
if (sf != null)
{
var targettxtfile = await Windows.Storage.FileIO.ReadTextAsync(sf);
var sbProcessedTextToWrite = new StringBuilder(targettxtfile);
if (targettxtfile.IndexOf(contentItemId) >= 0)
{
string startmarker = new StringBuilder("[").Append(contentItemId).Append("#start]").ToString();
string endmarker = new StringBuilder("[").Append(contentItemId).Append("#end]").ToString();
int start = sbProcessedTextToWrite.ToString().IndexOf(startmarker);
int end = sbProcessedTextToWrite.ToString().IndexOf(endmarker);
int slen = end + endmarker.Length - start;
//compute position to remove
sbProcessedTextToWrite.Remove(start, slen);
}
using (IRandomAccessStream fileStream = await sf.OpenAsync(FileAccessMode.ReadWrite))
{
using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
{
using (DataWriter dataWriter = new DataWriter(outputStream))
{
dataWriter.WriteString(sbProcessedTextToWrite.ToString());
await dataWriter.StoreAsync();
// For the in-memory stream implementation we are using, the flushAsync call
// is superfluous,but other types of streams may require it.
await dataWriter.FlushAsync();
// In order to prolong the lifetime of the stream, detach it from the
// DataWriter so that it will not be closed when Dispose() is called on
// dataWriter. Were we to fail to detach the stream, the call to
// dataWriter.Dispose() would close the underlying stream, preventing
// its subsequent use by the DataReader below.
dataWriter.DetachStream();
}
//same here flush the outputStream as well
await outputStream.FlushAsync();
}
}
}
}
Some references for this code

Categories