6

Ho il seguente codice in un Windows 8 C# app che recupera un'immagine da un server e lo memorizza:UnauthorizedAccessException durante il salvataggio di un file

 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; 
    } 

Sembra che io casualmente si verificano errori in questa particolare linea:

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

Non sempre accade, quindi non sono sicuro di come individuare il problema. Tutti i dettagli di errore sono qui:

UnauthorizedAccessException è stato catturato

Accesso negato. (Eccezione da HRESULT: 0x80070005 (E_ACCESSDENIED)) a System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (Task compito) a System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task compito) a System.Runtime.CompilerServices. TaskAwaiter`1.GetResult() a TestApp.MainPage.d__4.MoveNext() in d: \ TestApp \ TestApp \ MainPage.xaml.cs: linea Aggiornamento 86

risposta

6

- Il "Accesso negato" errori sono essere causato da più cose.

La prima causa ha a che fare con il download dell'immagine. Sembra che qualcosa nel codice di download stia tenendo aperto il file. Ho semplificato il codice di download qui sotto.

La seconda causa ha a che fare con l'oggetto BitmapImage che tiene aperto il file. Vedi questo post per maggiori informazioni: Access Denied when deleting image file previously used in DataTemplate in WinRT

Un modo per aggirare il secondo problema è quello di utilizzare un stream invece di un Uri per inizializzare la BitmapImage.

Ecco una versione che funziona per me (il codice originale è anche qui, ma commentata):

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; 
+0

Hmm, ora sto ricevendo una UnauthorizedAccessException (Accesso negato. (Eccezione da HRESULT: 0x80070005 (E_ACCESSDENIED))) a 'var stream = attende imageFile.OpenAsync (Windows.Storage.FileAccessMode.Read);'. Probabilmente un problema di permessi questa volta? Qualche idea? :/ – ReignOfComputer

+2

@ReignOfComputer - Guarda il mio post aggiornato. È cambiato parecchio. –

+0

Omg lo ha fatto grazie mille!Sei fantastico! : D – ReignOfComputer

1

Sono stato di fronte lo stesso problema quando ho scaricato il documento pdf a localfolder di file e provato per visualizzarlo. Non posso dire in modo affidabile perché questo sta accadendo, ma questo piccolo hack mi ha aiutato a risolvere questo:

Invece di usare

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

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

Io uso questo:

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 
} 
1

Se si dispone di l'opzione per utilizzare CreationCollisionOption. GenerateUniqueName anziché ReplaceExisting, provare a utilizzare questo.

Almeno ha risolto il problema per me.