下载并保存 PDF 以供查看

Download and Save PDF for viewing

我正在尝试从我的应用程序下载 PDF 文档并将其显示在 IBooks 中,或者至少在下载完成后使其可供阅读。

我遵循了 Xamarin 的下载示例,它允许我下载 PDF 并将其保存在本地。它也以错误的编码保存。

这是我目前尝试过的方法。

private void PdfClickHandler()
{
    var webClient = new WebClient();

    webClient.DownloadStringCompleted += (s, e) => {
        var text = e.Result; // get the downloaded text
        string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        string localFilename = $"{_blueways}.pdf";
        // writes to local storage
        File.WriteAllText(Path.Combine(documentsPath, localFilename), text); 

        InvokeOnMainThread(() => {
            new UIAlertView("Done", "File downloaded and saved", null, "OK", null).Show();
        });
    };

    var url = new Uri(_blueway.PDF);
    webClient.Encoding = Encoding.UTF8;
    webClient.DownloadStringAsync(url);
}

不要对 "binary" 数据使用 DownloadStringAsync,请使用 DownloadDataAsync:

Downloads the resource as a Byte array from the URI specified as an asynchronous operation.

private void PdfClickHandler ()
{
    var webClient = new WebClient ();

    webClient.DownloadDataCompleted += (s, e) => {
        var data = e.Result;
        string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        string localFilename = $"{_blueways}.pdf";
        File.WriteAllBytes (Path.Combine (documentsPath, localFilename), data);
        InvokeOnMainThread (() => {
            new UIAlertView ("Done", "File downloaded and saved", null, "OK", null).Show ();
        });
    };
    var url = new Uri ("_blueway.PDF");
    webClient.DownloadDataAsync (url);
}

这是从远程服务器下载 PCL Xamarin 文件的示例代码。 我使用了 Nuget 中提供的 PCLStorage 库包。您只需要下载并安装到您的项目中即可。

 public  async void Downloadfile(string Url)
    {
        try
        {
            Uri url = new Uri(Url);
            var client = new HttpClient();


            IFolder rootfolder = FileSystem.Current.LocalStorage;
            IFolder appfolder = await rootfolder.CreateFolderAsync("Download", CreationCollisionOption.OpenIfExists);
            IFolder dbfolder = await appfolder.CreateFolderAsync("foldername", CreationCollisionOption.OpenIfExists);
            IFile file = await dbfolder.CreateFileAsync(strReport_name, CreationCollisionOption.ReplaceExisting);
            using (var fileHandler = await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
            {
                var httpResponse = await client.GetAsync(url);
                byte[] dataBuffer = await httpResponse.Content.ReadAsByteArrayAsync();
                await fileHandler.WriteAsync(dataBuffer, 0, dataBuffer.Length);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

// 检索 URL
var pdfUrl = new Uri("url.pdf"); //在此处输入您的 PDF 路径

// 使用设备浏览器打开 PDF URL 进行下载
Device.OpenUri(pdfUrl);

//首先创建模型Class文件下载

public class FileDownload
{
    public string FileUrl { get; set; }
    public string FileName { get; set; }
}

//在 xaml 文件中为我们需要执行下载功能的按钮创建一个视图

 <ImageButton BackgroundColor="Transparent"    Clicked="DownloadFile_Clicked" x:Name="ImgFileReportDownload_ViewResult" IsVisible="False">
                        <ImageButton.Source>
                            <FontImageSource Glyph="&#xf019;"
                                         Color="#1CBB8C"
                                         Size="30"
                                         FontFamily="{StaticResource FontAwesomeSolid}">
                            </FontImageSource>
                        </ImageButton.Source>
                    </ImageButton>

//在xaml.cs中创建了一个方法来点击按钮下载文件

    private async void DownloadFile_Clicked(object sender, EventArgs e)
    {
        
        var status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
        if (status == PermissionStatus.Granted)
        {
            Uri uri = new Uri(fileReportNameViewResult);
            string filename = System.IO.Path.GetFileName(uri.LocalPath);


            FileDownload fileDownload = new FileDownload();
      
            fileDownload.FileName = filename;
            fileDownload.FileUrl = fileReportNameViewResult;
            MessagingCenter.Send<FileDownload>(fileDownload, "Download");
        }
        else
        {
            status = await Permissions.RequestAsync<Permissions.StorageWrite>();
            if (status != PermissionStatus.Granted)
            {
                await DisplayAlert("Permission Denied!", "\nPlease go to your app settings and enable permissions.", "Ok");
                return;
            }
        }
    }

//在MainActivity.cs中,创建方法

 private void MessagingCenter()
    {
        Xamarin.Forms.MessagingCenter.Subscribe<FileDownload>(this, "Download", (s) =>
        {
            NotificationID += 4;
            var intent = new Intent(this, typeof(Service.DownloadManager));
            intent.PutExtra("url", s.FileUrl);
            intent.PutExtra("name", s.FileName);
            _layout.SetMinimumHeight(3000);
            _layout.Bottom = 350; ;

            Snackbar.Make(_layout, "Document is Downloading.", Snackbar.LengthShort)


                         .Show();
            StartService(intent);
        });
    }

//在Service文件夹中创建一个class DownloadManager.cs,复制下面所有代码并粘贴,只需更改Namespace

                                                                    using Android.App;
                                            using Android.Content;
                                            using Android.OS;
                                            using Android.Runtime;
                                            using Android.Views;
                                            using Android.Widget;
                                            using System;
                                            using System.Collections.Generic;
                                            using System.IO;
                                            using System.Linq;
                                            using System.Net;
                                            using System.Text;
                                            using System.Threading.Tasks;
                                            using Xamarin.Forms;

                                            namespace App.Droid.Service
                                            {
                                                [Service]
                                                public class DownloadManager : Android.App.Service
                                                {
                                                    AndroidNotificationManager NotificationManager = new AndroidNotificationManager();
                                                    public override IBinder OnBind(Intent intent)
                                                    {
                                                        return null;
                                                    }
                                                    public override void OnCreate()
                                                    {

                                                    }
                                                    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
                                                    {            
                                                        Task.Run(() =>
                                                        {
                                                            int messageId = ++MainActivity.NotificationID;

                                                            string url = intent.GetStringExtra("url");
                                                            string filename = intent.GetStringExtra("name");
                                                            string extension = url.Substring(url.LastIndexOf('.'));
                                                            if (!filename.EndsWith(extension))
                                                            {
                                                                filename += extension;
                                                            }
                                                            NotificationManager.ScheduleNotification(filename, "", messageId);
                                                            String TempFileName = "";

                                                            try
                                                            {
                                                                HttpWebRequest Http = (HttpWebRequest)WebRequest.Create(url);
                                                                WebResponse Response = Http.GetResponse();
                                                                long length = Response.ContentLength;
                                                                var stream = Response.GetResponseStream();

                                                           

                                                                string baseDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;

                                                                //string baseDir = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDownloads).AbsolutePath;

                                                                //string baseDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);                  

                                                                //string baseDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
                                                                baseDir = Path.Combine(baseDir, filename.Substring(filename.LastIndexOf('/') + 1).Replace(' ', '_'));
                                                                Directory.CreateDirectory(baseDir);

                                                                //string filePath = Path.Combine(documentsPath, name);

                                                                if (filename.Length > 18)
                                                                {
                                                                    TempFileName = filename.Substring(0, 18) + "...";
                                                                }
                                                                else
                                                                {
                                                                    TempFileName = filename;
                                                                }
                                                                FileInfo fi = new FileInfo(Path.Combine(baseDir, filename.Substring(filename.LastIndexOf('/') + 1).Replace(' ', '_')));

                                                                var fis = fi.OpenWrite();
                                                                long count = 0;

                                                                int begpoint = 0;


                                                                bool iscancelled = false;
                                                                MessagingCenter.Subscribe<CancelNotificationModel>(this, "Cancel", sender =>
                                                                {
                                                                    if (messageId == sender.ID)
                                                                    {
                                                                        iscancelled = true;
                                                                    }
                                                                });
                                                                while (true)
                                                                {
                                                                    try
                                                                    {
                                                                        if (iscancelled == true)
                                                                        {
                                                                            break;
                                                                        }
                                                                        // Read file
                                                                        int bytesRead = 0;
                                                                        byte[] b = new byte[1024 * 1024];
                                                                        bytesRead = stream.Read(b, begpoint, b.Length);
                                                                        
                                                                        if (bytesRead == 0)
                                                                            break;
                                                                        fis.Write(b, 0, bytesRead);
                                                                        fis.Flush();

                                                                        count += bytesRead;
                                                                        System.Diagnostics.Debug.WriteLine(count + "-" + length);
                                                                        if (count >= length)
                                                                            break;
                                                                        NotificationManager.ChangeProgress(TempFileName, (int)((count * 100) / length), messageId);

                                                                    }
                                                                    catch (Exception ex)
                                                                    {
                                                                        Http = (HttpWebRequest)WebRequest.Create(url);

                                                                        WebHeaderCollection myWebHeaderCollection = Http.Headers;
                                                                        Http.AddRange(count, length - 1);

                                                                        Response = Http.GetResponse();

                                                                        stream = Response.GetResponseStream();
                                                                    }
                                                                }
                                                                fis.Close();

                                                                NotificationManager.RemoveNotification(messageId);
                                                                if (iscancelled == false)
                                                                {

                                                                    new AndroidNotificationManager().DownloadCompleted(filename, "Download Completed", Path.Combine(baseDir, filename), ++messageId);
                                                                }

                                                            }
                                                            catch (Exception ex)
                                                            {
                                                                NotificationManager.RemoveNotification(messageId);

                                                                NotificationManager.FileCancelled(filename, "Download Cancelled, Please try again", ++messageId);
                                                            }
                                                        });


                                                        return StartCommandResult.NotSticky;

                                                    }
                                                  
                                                    public override void OnDestroy()
                                                    {

                                                    }

                                                }
                                                public class CancelNotificationModel
                                                {
                                                    public int ID { get; set; }
                                                }
                                            }

//在服务文件夹中创建一个class AndroidNotificationManager.cs

                    using Android.App;
                    using Android.Content;
                    using Android.OS;
                    using Android.Runtime;
                    using Android.Views;
                    using Android.Widget;
                    using AndroidX.Core.App;
                    using System;
                    using System.Collections.Generic;
                    using System.Linq;
                    using System.Text;
                    using Xamarin.Essentials;
                    using AndroidApp = Android.App.Application;

                    namespace App.Droid.Service
                    {
                        public class AndroidNotificationManager
                        {
                            const string channelId = "default";
                            const string channelName = "Default";
                            const string channelDescription = "The default channel for notifications.";
                            const int pendingIntentId = 0;

                            public const string TitleKey = "title";
                            public const string MessageKey = "message";

                            bool channelInitialized = false;

                            NotificationManager manager;
                            NotificationCompat.Builder builder;
                            public event EventHandler NotificationReceived;

                            public void Initialize()
                            {
                                CreateNotificationChannel();
                            }

                            public void RemoveNotification(int messageid)
                            {
                                manager.Cancel(messageid);
                            }
                            public int ScheduleNotification(string title, string message, int messageId, bool isInfinite = false)
                            {
                                if (!channelInitialized)
                                {
                                    CreateNotificationChannel();
                                }



                                Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
                                intent.PutExtra(TitleKey, title);
                                intent.PutExtra(MessageKey, message);

                                PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);

                                builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)

                                    .SetContentTitle(title)
                                    .SetContentText(message)
                                                         .SetPriority(NotificationCompat.PriorityLow)
                                    .SetVibrate(new long[] { 0L })
                                    .SetProgress(100, 0, isInfinite)
                                     .SetSmallIcon(Resource.Drawable.checkcircle);


                                var notification = builder.Build();
                                manager.Notify(messageId, notification);

                                return messageId;
                            }


                            public void ChangeProgress(string filename, int progress, int messageId)
                            {
                                try
                                {
                                    var actionIntent1 = new Intent();

                                    actionIntent1.SetAction("Cancel");
                                    actionIntent1.PutExtra("NotificationIdKey", messageId);
                                    var pIntent1 = PendingIntent.GetBroadcast(Android.App.Application.Context, 0, actionIntent1, PendingIntentFlags.CancelCurrent);

                                    var ProgressBuilder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
                                    .SetSmallIcon(Resource.Drawable.checkcircle)
                                     .SetContentTitle(filename)
                    .SetVibrate(new long[] { 0L })
                    .AddAction(Resource.Drawable.checkcircle, "Cancel", pIntent1)
                                         .SetPriority(NotificationCompat.PriorityLow)
                                 .SetProgress(100, progress, false)
                                .SetContentText(progress + "%")
                                .SetAutoCancel(false);

                                    System.Diagnostics.Debug.WriteLine(progress);
                                    manager.Notify(messageId, ProgressBuilder.Build());
                                }
                                catch
                                {

                                }
                            }
                            public void DownloadCompleted(string filenametitle, string Message, string filepath, int messageId)
                            {
                                try
                                {
                                    if (!channelInitialized)
                                    {
                                        CreateNotificationChannel();
                                    }

                                    var CompletedBuilder = new NotificationCompat.Builder(AndroidApp.Context, channelId)

                                          .SetContentTitle(filenametitle)
                                          .SetContentText(Message)
                                          .SetAutoCancel(true)
                                           .SetSmallIcon(Resource.Drawable.checkcircle);

                                    Intent it = OpenFile(filepath, filenametitle);
                                  

                                    if (it != null)
                                    {
                                        PendingIntent contentIntent =
                                             PendingIntent.GetActivity(AndroidApp.Context,
                                                       pendingIntentId,
                                                       it,
                                                       PendingIntentFlags.OneShot

                             );

                                        CompletedBuilder.SetContentIntent(contentIntent);

                                       
                                    }
                                    var notification = CompletedBuilder.Build();

                                    manager.Notify(messageId, notification);
                                }
                                catch (Exception ex)
                                {
                                }
                            }
                            public void FileCancelled(string filenametitle, string Message, int messageId)
                            {

                                if (!channelInitialized)
                                {
                                    CreateNotificationChannel();
                                }

                                var CompletedBuilder = new NotificationCompat.Builder(AndroidApp.Context, channelId)

                                      .SetContentTitle(filenametitle)
                                      .SetContentText(Message)
                                      .SetAutoCancel(true)
                                       .SetSmallIcon(Resource.Drawable.checkcircle)
                                      .SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);

                                var notification = CompletedBuilder.Build();
                                manager.Notify(messageId, notification);
                            }
                            public void ReceiveNotification(string title, string message)
                            {
                              
                            }

                            void CreateNotificationChannel()
                            {
                                manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);

                                if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
                                {
                                    var channelNameJava = new Java.Lang.String(channelName);
                                    var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Low)
                                    {
                                        Description = channelDescription
                                    };
                                    manager.CreateNotificationChannel(channel);
                                }

                                channelInitialized = true;
                            }
                            public Intent OpenFile(string filePath, string fileName)
                            {
                                try
                                {
                                    string application = "";
                                    string extension = fileName.Substring(fileName.IndexOf('.'));

                                    switch (extension.ToLower())
                                    {
                                        case ".doc":
                                        case ".docx":
                                            application = "application/msword";
                                            break;
                                        case ".pdf":
                                            application = "application/pdf";
                                            break;
                                        case ".xls":
                                        case ".xlsx":
                                            application = "application/vnd.ms-excel";
                                            break;
                                        case ".jpg":
                                        case ".jpeg":
                                        case ".png":
                                            application = "image/jpeg";
                                            break;
                                        case ".mp4":
                                            application = "video/mp4";
                                            break;
                                        default:
                                            application = "*/*";
                                            break;
                                    }

                                    Java.IO.File file = new Java.IO.File(filePath);
                                    bool isreadable =
                                   file.SetReadable(true);
                                    string ApplicationPackageName = AppInfo.PackageName;
                                    var context = Android.App.Application.Context;
                                    var component = new Android.Content.ComponentName(context, Java.Lang.Class.FromType(typeof(AndroidX.Core.Content.FileProvider)));
                                    var info = context.PackageManager.GetProviderInfo(component, Android.Content.PM.PackageInfoFlags.MetaData);
                                    var authority = info.Authority;
                                    Android.Net.Uri uri = AndroidX.Core.Content.FileProvider.GetUriForFile(Android.App.Application.Context, authority, file);
                                    Intent intent = new Intent(Intent.ActionView);
                                    System.IO.File.AppendAllText((filePath + "backdebug.txt"), System.Environment.NewLine + "Point 3 uri done ");

                                  


                                    intent.SetDataAndType(uri, application);


                                    intent.AddFlags(ActivityFlags.GrantReadUriPermission);
                                    intent.AddFlags(ActivityFlags.NoHistory);
                                    intent.AddFlags(ActivityFlags.NewTask);

                                    System.IO.File.AppendAllText((filePath + "backdebug.txt"), System.Environment.NewLine + "Point 4open file last ");



                                    return intent;
                                }
                                catch (Exception ex)
                                {
                                    Intent it = new Intent();
                                    it.PutExtra("ex", ex.Message);
                                    System.IO.File.AppendAllText((filePath + "backdebug.txt"), System.Environment.NewLine + "Point 4 uri done " + ex.Message);

                                    return it;

                                }


                            }

                        }
                    }