locked
File Save / Open Conflict

    Question

  • I am trying to download a file to local storage then open that file.  The file saves okay and if I close/open the app the file works as expected.  However, if I try to open the file without closing the app first I get E_ACCESSDENIED.  It seems as though the file save is keeping a handle on the file but as far as I can tell I'm closing/disposing of everything I should be.  What am I missing?

    thanks.

    HttpClient httpClient = new HttpClient();
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
    HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

    // create a local file to save to
    string filename = uri.Substring(uri.LastIndexOf("/") + 1, uri.Length - uri.LastIndexOf("/") - 1);
    StorageFile imageFile = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
    var ras = await imageFile.OpenAsync(FileAccessMode.ReadWrite);

    // write the data to the file
    DataWriter writer = new DataWriter(ras.GetOutputStreamAt(0));
    writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());

    // close 
    await writer.StoreAsync();
    await writer.FlushAsync();
    writer.DetachStream();

    // cleanup
    response.Dispose();
    await ras.FlushAsync();
    writer.Dispose();
    ras.Dispose();


    Thursday, April 24, 2014 8:08 AM

Answers

  • I finally figured it out.  The difference seems to be that I was creating the output stream inline and so didn't have a name to dispose of it with.  This code works great to write a file and tidy everything up properly.

    public async Task DownloadFile(string uri, StorageFolder folder)
    {
        try
        {
            // make the web call to get the file
            HttpClient httpClient = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
            HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

            // create a local file to save to
            string filename = uri.Substring(uri.LastIndexOf("/") + 1, uri.Length - uri.LastIndexOf("/") - 1);
            StorageFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

            using (var ras = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (var outStream = ras.GetOutputStreamAt(0))
                {
                    using (DataWriter writer = new DataWriter(outStream))
                    {
                        writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());

                        // close 
                        await writer.StoreAsync();
                        await writer.FlushAsync();
                        writer.DetachStream();

                        await ras.FlushAsync();

                        // cleanup
                        response.Dispose();
                        writer.Dispose();
                        ras.Dispose();
                    }
               }
            }
        }
        catch (Exception exc)
        {
            string x = "y";
        }
    }

    Friday, April 25, 2014 12:36 PM

All replies

  • how are you opening the file? i tried with the launcher, which worked great. do you have a demo case we can play with so we can help?

    Microsoft Certified Solutions Developer - Windows Store Apps Using C#

    Thursday, April 24, 2014 9:04 AM
  • This is how I open the file. The call my GetFile function works find, it is the OpenAsync to get the stream that returns the E_ACCESSDENIED.  

    StorageFile audioFile = await App.GetFile(uri);

    if(audioFile != null)

    {

       var stream = await audioFile.OpenAsync(Windows.Storage.FileAccessMode.Read);

        // kablooey!

    }

    public async static Task<StorageFile> GetFile(string uri)
    {
           string filename = uri.Substring(uri.LastIndexOf("/") + 1, uri.Length - uri.LastIndexOf("/") - 1);

           StorageFolder folder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync("fileCache", CreationCollisionOption.OpenIfExists);

           try
           {
                 StorageFile file = await StorageFile.GetFileFromPathAsync(folder.Path + "\\" + filename);
                 return file;
           }
           catch (Exception exc)
          {
               return null;
           }
    }

    Thursday, April 24, 2014 7:01 PM
  • can you post a sample so can see the entire flow?

    Microsoft Certified Solutions Developer - Windows Store Apps Using C#

    Friday, April 25, 2014 6:51 AM
  • I finally figured it out.  The difference seems to be that I was creating the output stream inline and so didn't have a name to dispose of it with.  This code works great to write a file and tidy everything up properly.

    public async Task DownloadFile(string uri, StorageFolder folder)
    {
        try
        {
            // make the web call to get the file
            HttpClient httpClient = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
            HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

            // create a local file to save to
            string filename = uri.Substring(uri.LastIndexOf("/") + 1, uri.Length - uri.LastIndexOf("/") - 1);
            StorageFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

            using (var ras = await file.OpenAsync(FileAccessMode.ReadWrite))
            {
                using (var outStream = ras.GetOutputStreamAt(0))
                {
                    using (DataWriter writer = new DataWriter(outStream))
                    {
                        writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());

                        // close 
                        await writer.StoreAsync();
                        await writer.FlushAsync();
                        writer.DetachStream();

                        await ras.FlushAsync();

                        // cleanup
                        response.Dispose();
                        writer.Dispose();
                        ras.Dispose();
                    }
               }
            }
        }
        catch (Exception exc)
        {
            string x = "y";
        }
    }

    Friday, April 25, 2014 12:36 PM