保存文件时出现UnauthorizedAccessException

时间:2013-06-08 13:48:29

标签: c# asynchronous windows-8 error-handling unauthorizedaccessexcepti

我在Windows 8 C#应用程序中有以下代码,它从服务器获取图像并存储它:

        private async Task httpFetcher()
    {
        HttpClient httpClient = new HttpClient();
        HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Get, "http://www.example.com/fakeImageRotator.php"); // FOR EXAMPLE
        HttpResponseMessage response = await httpClient.SendAsync(request,
            HttpCompletionOption.ResponseHeadersRead);

        Uri imageUri;
        BitmapImage image = null;

        try
        {
            var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
         "test.png", CreationCollisionOption.ReplaceExisting);
            var fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite);
            DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0));
            writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
            await writer.StoreAsync();
            writer.DetachStream();
            await fs.FlushAsync();
            writer.Dispose();

            if (Uri.TryCreate(imageFile.Path, UriKind.RelativeOrAbsolute, out imageUri))
            {
                image = new BitmapImage(imageUri);
            }

        }
        catch (Exception e)
        {
            return;
        }

        image1.Source = image;
    }

看来我在这一特定行上随机出错:

                var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
         "test.png", CreationCollisionOption.ReplaceExisting);

并非总是如此,所以我不确定如何查明问题。所有错误详情都在这里:

  

发现了UnauthorizedAccessException

     

访问被拒绝。 (HRESULT的例外情况:0x80070005   (E_ACCESSDENIED))   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务   任务)   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务   任务)在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()   在TestApp.MainPage.d__4.MoveNext()中   d:\ TestApp \ TestApp \ MainPage.xaml.cs:第86行

3 个答案:

答案 0 :(得分:6)

更新 - “拒绝访问”错误是由多件事引起的。

第一个原因与下载图像有关。下载代码中出现的东西是保持打开文件。我简化了下面的下载代码。

第二个原因与保持打开文件的BitmapImage对象有关。有关详情,请参阅此帖子:Access Denied when deleting image file previously used in DataTemplate in WinRT

解决第二个问题的另一种方法是使用stream代替Uri初始化BitmapImage

这是一个适合我的版本(您的原始代码也在这里,但注释掉了):

var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
  "test.png", CreationCollisionOption.ReplaceExisting);
/*
var fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite);
DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0));
writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
await writer.StoreAsync();
writer.DetachStream();
await fs.FlushAsync();
writer.Dispose();

if (Uri.TryCreate(imageFile.Path, UriKind.RelativeOrAbsolute, out imageUri))
{
    image = new BitmapImage(imageUri);
}
*/
var fs = await imageFile.OpenStreamForWriteAsync();
await response.Content.CopyToAsync(fs);
await fs.FlushAsync();
// you may want to have this Dispose as part of a 
// finally block (try/ catch/ finally)
fs.Dispose();

var bs = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
image = new BitmapImage();
image.SetSource(bs);
...
image1.Source = image;

答案 1 :(得分:1)

当我将pdf文档下载到LocalFolder文件并尝试显示它时,我遇到了同样的问题。我无法确切地说出为什么会发生这种情况,但这个小小的黑客帮助我解决了这个问题:

而不是使用

try
{
  StorageFile storage = await ApplicationData.Current.LocalFolder.CreateFileAsync(
    fileName, CreationCollisionOption.ReplaceIfExists);

  //work with file
}
catch (Exception) { ... }

我现在用这个:

StorageFile storage = null;
try 
{ 
  //First try to get the file
  storage = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName); 
}
catch (Exception) 
{ 
  //Ignore this exception
}

try
{
  //If the storage file is still null, create it
  if (storage == null)
    storage = await ApplicationData.Current.LocalFolder.CreateFileAsync(
      fileName, CreationCollisionOption.OpenIfExists);

  //Work with file
}
catch (Exception)
{
  //Process exception
}

答案 2 :(得分:1)

如果您可以选择使用CreationCollisionOption。 GenerateUniqueName 而不是ReplaceExisting,请尝试使用此功能。

至少它解决了我的问题。

相关问题