问题
I have the following code in a Windows 8 C# app which fetches an image from a server and stores it:
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;
}
It appears that I randomly get errors on this particular line:
var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
"test.png", CreationCollisionOption.ReplaceExisting);
It doesn't always happen, so I'm not sure how to pinpoint the issue. All the error details are here:
UnauthorizedAccessException was caught
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at TestApp.MainPage.d__4.MoveNext() in d:\TestApp\TestApp\MainPage.xaml.cs:line 86
回答1:
Update - The "Access Denied" errors are being caused by multiple things.
The first cause has to do with the downloading of the image. It appears something in download code is holding open the file. I have simplified the download code below.
The second cause has to do with the BitmapImage
object holding open the file. See this post for more info: Access Denied when deleting image file previously used in DataTemplate in WinRT
One way around the second issue is to use a stream
instead of a Uri
to initialize the BitmapImage
.
Here is a version that works for me (your original code is also here, but commented out):
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;
回答2:
I have been facing the same problem when I downloaded the pdf document to LocalFolder file and tried to display it. I can't tell reliably why this is happening, but this little hack helped me to solve this:
Instead of using
try
{
StorageFile storage = await ApplicationData.Current.LocalFolder.CreateFileAsync(
fileName, CreationCollisionOption.ReplaceIfExists);
//work with file
}
catch (Exception) { ... }
I now use this:
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
}
回答3:
If you have the option to use CreationCollisionOption.GenerateUniqueName instead of ReplaceExisting, try to use this.
At least it solved the problem for me.
来源:https://stackoverflow.com/questions/17000137/unauthorizedaccessexception-while-saving-a-file