Xamarin.Forms 将文件 (pdf) 保存在本地存储中并使用默认查看器打开

Posted

技术标签:

【中文标题】Xamarin.Forms 将文件 (pdf) 保存在本地存储中并使用默认查看器打开【英文标题】:Xamarin.Forms save file (pdf) in local storage and open with the default viewer 【发布时间】:2020-06-09 04:19:54 【问题描述】:

已修改问题

android 中,我需要将 pdf 文件下载到“Doc​​uments”文件夹并使用默认程序打开它。 我下载了文档并将其存储在一个字节数组中。 然后我调用这个方法:

    /// <summary>
    /// Save data bytes on "My documents" folder and open
    /// </summary>
    /// <param name="fileName">Filename, for example: "Test.pdf"</param>
    /// <param name="data">Array of bytes to save</param>
    /// <returns>True if success or false if error</returns>
    public bool SaveAndOpen(string fileName, byte[] data)
    
        try
        
            // Get my documents path
            string filePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);
            // Combine with filename
            string fullName = Path.Combine(filePath, fileName);

            // If the file exist on device delete it
            if (File.Exists(fullName))
            
                // Note: In the second run of this method, the file exists
                File.Delete(fullName);
            

            // Write bytes on "My documents"
            File.WriteAllBytes(fullName, data);

            // Launch file as process
            Process.Start(fullName);

            return true;
        
        catch (Exception ex)
        
            Console.WriteLine("ERROR: " + ex.Message + ex.StackTrace);
            return false;
        
    

问题是用默认的pdf阅读器打开pdf文档。

“Process.Start(fullName);”行抛出异常

System.ComponentModel.Win32Exception (0x80004005):访问被拒绝

感谢您的宝贵时间!

【问题讨论】:

string filePath = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 嗯...那会是哪条路?请完整路径值。 文件路径为:/data/user/0/MySampleApp.MySampleApp/files 全名为:/data/user/0/MySampleApp.MySampleApp/files/Test.pdf 这只是在您的应用程序的私有目录中。没有其他应用程序或文件管理器具有访问权限。如果您希望文件管理器具有访问权限,请选择另一个存储位置进行下载。 /storage/emulated/0/Documents 将是路径。但不要硬编码。 您是否实现了向用户询问运行时权限? In Android, 哪个版本? 【参考方案1】:

我找到了保存和打开文件的方法:

    /// <summary>
    /// Save data bytes on "My documents" folder and open
    /// </summary>
    /// <param name="fileName">Filename, for example: "Test.pdf"</param>
    /// <param name="data">Array of bytes to save</param>
    /// <returns>True if success or false if error</returns>
    public bool SaveAndOpen(string fileName, byte[] data)
    
        try
        
            // Get my downloads path
            string filePath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryDownloads);

            // Combine with filename
            string fullName = Path.Combine(filePath, fileName);

            // If the file exist on device delete it
            if (File.Exists(fullName))
            
                // Note: In the second run of this method, the file exists
                File.Delete(fullName);
            

            // Write bytes on "My documents"
            File.WriteAllBytes(fullName, data);

            // Get the uri for the saved file
            Android.Net.Uri file = Android.Support.V4.Content.FileProvider.GetUriForFile(
                this,
                this.PackageName + ".fileprovider",
                new Java.IO.File(fileName));
            Intent intent = new Intent(Intent.ActionView);
            intent.SetDataAndType(file, "application/pdf");
            intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission | ActivityFlags.NewTask);
            this.ApplicationContext.StartActivity(intent);

            return true;
        
        catch (Exception ex)
        
            Console.WriteLine("ERROR: " + ex.Message + ex.StackTrace);
            return false;
        
    

需要在运行时请求权限。我使用了 Nuget 上可用的 Plugin.Permisions:

    Plugin.Permissions.PermissionsImplementation.Current.RequestPermissionsAsync(
         new Plugin.Permissions.Abstractions.Permission[]
         
             Plugin.Permissions.Abstractions.Permission.Storage,
             Plugin.Permissions.Abstractions.Permission.MediaLibrary
         );

还在 AndroidManifest.xml 文件中添加一个提供程序:

<application android:label="My app" android:icon="@mipmap/icon">
    <provider android:name="android.support.v4.content.FileProvider" android:authorities="$applicationId.fileprovider" android:exported="false" android:grantUriPermissions="true">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
    </provider>
</application>

在同一个 AndroidManifest 中添加权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />

并在 Resources/xml/file_paths.xml 中添加外部路径

<external-path name="external_files" path="."/>

不知道我是否不需要权限,但这种方式可行。

【讨论】:

经过 6 小时的冲浪终于我找到了这个答案,它解决了我的问题,谢谢。 @Duefectu 这个的任何ios版本?

以上是关于Xamarin.Forms 将文件 (pdf) 保存在本地存储中并使用默认查看器打开的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xamarin Forms 中生成 PDF 第一页的缩略图

如何在 Android 11 Xamarin Forms 中下载和打开 PDF

Xamarin.Forms 在 webview 中打开来自 https://docs.google.com/viewer?url=pdf 的 url

Syncfusion Xamarin.Forms生成的PDF格式的文本

下载PDF作为字节流,然后在Xamarin.Forms中的默认Android应用程序中打开

Xamarin.Forms学习之Page Navigation