应用程序无法进一步处理 Xamarin 中的磁盘/文件夹

Posted

技术标签:

【中文标题】应用程序无法进一步处理 Xamarin 中的磁盘/文件夹【英文标题】:App cannot further process disks / folder in Xamarin 【发布时间】:2021-11-09 08:58:29 【问题描述】:

嘿,我是 Xamarin 的新手,希望你们能帮助我。由于 xamarin 中没有默认的文件夹选择器,我想自己实现它。问题是 UWP 和 android 向我抛出了这个异常:

System.UnauthorizedAccessException H结果=0x80070005 Nachricht = 拒绝访问路径“C:\Users\imtt\AppData\Local\Packages\3ef1aa30-7ffe-4ece-84c7-d2eaf1f8634b_wvdsmkc2tee92\LocalState\Test\199.jpg”。 Quelle = System.IO.FileSystem Stapelüberwachung: 北 System.IO.FileSystem.DeleteFile(String fullPath) bei System.IO.File.Delete(字符串路径) 在 C:\Users\imtt\source\repos\MinimalReproducibleExample\MinimalReproducibleExample\MinimalReproducibleExample\ViewModel.cs 中的 BEI MinimalReproducibleExample.ViewModel.DeleteFiles():Zeile107 北 Xamarin.Forms.Command.c__DisplayClass4_0.<.ctor>b__0(Object o) 北 Xamarin.Forms.Command.Execute(对象参数) 北 Xamarin.Forms.ButtonElement.ElementClicked(VisualElement visualElement, IButtonElement ButtonElementManager) 北 Xamarin.Forms.Button.SendClicked() bei Xamarin.Forms.Platform.UWP.ButtonRenderer.OnButtonClick(Object sender, RoutedEventArgs e)

这是 xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="MinimalReproducibleExample.MainPage">
<StackLayout>
    <Button Text="Add Image" Command="Binding AddImage"/>
    <Button Text="Delete Images" Command="Binding DeleteImages"/>
    <Image Source="Binding CreatedImage"/>
</StackLayout>

这是代码隐藏:

using Xamarin.Forms;

namespace MinimalReproducibleExample

   public partial class MainPage : ContentPage
   
      public MainPage()
      
        BindingContext = new ViewModel();
        InitializeComponent();
      
   
 
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows.Input;
    using Xamarin.Essentials;
    using Xamarin.Forms;

    namespace MinimalReproducibleExample

    public class ViewModel : INotifyPropertyChanged
    

        private ImageSource image;
        private string fileFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Test");
        public ICommand AddImage  get; 
        public ICommand DeleteImages  get; 

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string name = "")
        
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        

        public ViewModel()
        
            AddImage = new Command(ShowFilePicker);
            DeleteImages = new Command(DeleteFiles);
        

        public ImageSource CreatedImage
        
            get => image;
            set
            
                image = value;
                OnPropertyChanged();
            
        


        public async void ShowFilePicker()
        
            FilePickerFileType filePickerFileType = new FilePickerFileType(
                    new Dictionary<DevicePlatform, IEnumerable<string>> 
                         DevicePlatform.ios, new []  "jpeg", "png", "mp3", "mpeg4Movie", "plaintext", "utf8PlainText", "html"  ,
                         DevicePlatform.Android, new []  "image/jpeg", "image/png", "audio/mp3", "audio/mpeg", "video/mp4", "text/*", "text/html"  ,
                         DevicePlatform.UWP, new [] "*.jpg", "*.jpeg", "*.png", "*.mp3", "*.mp4", "*.txt", "*.html"  
                    );

            PickOptions pickOptions = new PickOptions
            
                PickerTitle = "Wählen Sie eine oder mehrere Dateien aus",
                FileTypes = filePickerFileType,
            ;

            IEnumerable<FileResult> pickedFiles = await FilePicker.PickMultipleAsync(pickOptions);
            List<FileResult> results = pickedFiles.ToList();

            if (results != null && results.Count > 0)
            
                foreach (FileResult fileResult in results)
                

                    using (Stream stream = await fileResult.OpenReadAsync())
                    

                        DirectoryInfo directoryInfo = Directory.CreateDirectory(fileFolder);

                        string directoryPath = directoryInfo.FullName;

                        string filepath = Path.Combine(directoryPath, fileResult.FileName);

                        try
                        

                            byte[] bArray = new byte[stream.Length];

                            using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate))
                            
                                stream.Read(bArray, 0, (int)stream.Length);
                                int length = bArray.Length;
                                fs.Write(bArray, 0, length);
                            

                            CreatedImage = ImageSource.FromFile(filepath);
                        
                        catch (Exception exc)
                        
                        

                    
                
            
        

        public void DeleteFiles()
        
            string[] filePaths = Directory.GetFiles(fileFolder);

            foreach(string filePath in filePaths)
            
                File.Delete(filePath);
            
        
    

我已经通过 Windows 设置为我的应用授予了对文件系统的访问权限,还授予了 Android 部分的读写权限。我什至给了 UWP 部分的“broadFileAccess”,即使这样也没有成功。

这与另一个问题相交,UWP部分可以将文件写入“Environment.SpecialFolder.LocalApplicationData”中的文件夹,但不允许删除该文件夹中的文件。

这和 UWP 和 Android 的沙盒有关系吗?

【问题讨论】:

Environment.SpecialFolder.LocalApplicationData 匹配的文件夹是UWP平台的本地存储。并且拥有完全权限,可以读写文件。 @NicoZhu-MSFT 感谢您的回复,我添加了代码 sn-ps 用于文件创建和删除。 我认为不允许您删除文件的原因是您没有在写入后刷新和处置FileStream。这使得该文件仍在使用中。请尝试致电FlushDispose @NicoZhu-MSFT 我尝试了您的 Flush and Dispose 方法。遗憾的是,这并没有成功。 using 不能确保 using-block 中所有使用过的资源都被释放? @NicoZhu-MSFT 非常感谢你:) 【参考方案1】:

应用无法进一步处理 Xamarin 中的磁盘/文件夹

我用你的代码测试过,如果我们禁用CreatedImage = ImageSource.FromFile(filepath);这一行,问题是当你删除文件时,图像控制正在使用该文件。它会按预期工作。

我需要那个图像控件来显示图像

我们建议您使用流渲染图像,但不要直接从文件创建源。

例如

CreatedImage = ImageSource.FromStream(() => stream);

【讨论】:

流必须是 MemoryStream 类型,普通流是不行的

以上是关于应用程序无法进一步处理 Xamarin 中的磁盘/文件夹的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms 无法更改本地设备上 Xamarin.iOS 中的应用程序图标

无法使用 Xamarin.Android 中的 Xamarin.Mobile 组件保存联系人

Xamarin.Forms 中的全局异常处理

Andrioid FileProvider在Xamarin.Forms中的使用

xamarin 形成 xaml OnPlatform 无法处理绑定

无法反序列化当前 JSON 对象,xamarin.forms 中的错误