【问题标题】:How to open downloaded file on iOS如何在 iOS 上打开下载的文件
【发布时间】:2017-10-03 06:00:24
【问题描述】:

我们正在 Xamarin 中开发移动应用程序。接下来如何在 iOS 中完成:

  • 用户从 url 下载文件(向 REST API 发出 http 请求,使用 Authentication Basic 用户名:secretKey 进行保护)
  • 文件已保存到 iOS
  • 用户打开文件(允许使用 jpg、png、pdf、doc、docx、png)
  • 文件在默认应用程序中打开(例如用于图像图像查看器)

由于文件操作是平台特定的,这里是接口定义:

public interface IFileHelper
{
  void DownloadFileAndSave(Models.DocumentModel document);
}

Android 实现:

public class FileHelper : IFileHelper
{
  // download file and view status in download manager
  public void DownloadFileAndSave(Models.DocumentModel document)
  {
    DownloadManager dm = (DownloadManager)Android.App.Application.Context.GetSystemService(Context.DownloadService);
    string url = WebApiUtils.GetBaseUrl() + string.Format("Api/v1/Dms/{0}", document.UniqueId);
    DownloadManager.Request request = new Android.App.DownloadManager.Request(Android.Net.Uri.Parse(url)));

    request.AddRequestHeader("Authorization", "Basic " + WebApiUtils.GetEncodedCredentials(Auth.Users.Current));

    var downloadFile = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);
    string path = Path.Combine(downloadFile.AbsolutePath, document.FileName);
    request.SetDestinationUri(Android.Net.Uri.FromFile(new Java.IO.File(path)));
    request.SetMimeType(document.ContentType);  
    request.SetNotificationVisibility(DownloadVisibility.VisibleNotifyCompleted);

    dm.Enqueue(request);
}

在 Android 中,文件只是存储在文件系统中,并且使用默认安装在任何 Android 上的文件资源管理器(即我的文件 -> 设备存储 -> 下载),文件在默认应用程序中打开文件的 mime 类型。在 Android 上一切正常。

Apple iOS 实施:

public class FileHelper : IFileHelper
{
  public void DownloadFileAndSave(Models.DocumentModel document)
  {
    WebClient webClient = new WebClient();

    webClient.Headers.Add(HttpRequestHeader.Authorization, "Basic " + WebApiUtils.GetEncodedCredentials(Auth.Users.Current));
    webClient.DownloadDataAsync(new System.Uri(WebApiUtils.GetBaseUrl() + string.Format(Consts.ApiUrls.GetDocument, document.UniqueId)));

    webClient.DownloadDataCompleted += (sender, e) =>
    {
      byte[] content = e.Result;
      string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), document.FileName);

      // doesn't throw exception therefore saved ok
      File.WriteAllBytes(path, content);

      Uri uri = new Uri(String.Format("file://{0}", path));

      // doesn't work.
      Device.OpenUri(uri);
    };
  }
}

有没有其他方法可以在默认应用程序中打开下载的文件。如果我打开网址,例如http://example.com/files/file1.png 它在 safari 中打开文件,但我无法将 Authorization: Basic 标头放入 Device.OpenUri

我读到了Load Non-Web Documents with WebView,但您必须将每个文件构建为BundleResource

【问题讨论】:

  • 在你的iOS代码中,你评论说没有抛出异常,你能看到路径中的文件吗?
  • 另外,不确定你是否看过这个但看看这里 forums.xamarin.com/discussion/68919/… 它与你所拥有的类似的问题,我相信 OP 也解决了这里的问题
  • @CodeWarrior 谢谢你的链接,我错过了。该解决方案几乎可以工作。请参阅下面的答案。
  • @CodeWarrior 我没有在路径中看到文件,我只用System.IO.File.Exists(path);进行了测试
  • 您的答案在下面,您可以使用吗?

标签: c# android ios xamarin xamarin.ios


【解决方案1】:

正如 Code Warrior 所说,链接上发布了一种方法:https://forums.xamarin.com/discussion/36964/why-is-it-that-nothing-is-working-to-open-an-existing-local-pdf-file-in-the-ios-portion-of-my-pcl

但是保存图片操作不起作用,其他一切似乎都起作用。

public void DownloadFileAndSave(Models.DocumentModel document)
{
  WebClient webClient = new WebClient();
  webClient.Headers.Add(HttpRequestHeader.Authorization, "Basic " + WebApiUtils.GetEncodedCredentials(Auth.Users.Current));

  string tempPath = Path.GetTempPath();
  string localFilename = Path.GetFileName(document.FileName);
  string localPath = Path.Combine(tempPath, localFilename);

  webClient.DownloadFileCompleted += (sender, e) =>
  {
    Device.BeginInvokeOnMainThread(() =>
    {
      QLPreviewItemFileSystem prevItem = new QLPreviewItemFileSystem(localFilename, localPath); // ql = quick look
      QLPreviewController previewController = new QLPreviewController()
      {
        DataSource = new PreviewControllerDS(prevItem)
      };
      UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(previewController, true, null);
    });
  };

  // download file
  Uri uri = new System.Uri(WebApiUtils.GetBaseUrl() + string.Format(Consts.ApiUrls.GetDocument, document.UniqueId));
  webClient.DownloadFileAsync(uri, localPath);
}

保存图片 被触发时,我得到下一个错误:

2017-10-03 13:45:56.797 MyApp.iOS[477:61030] 视频 /private/var/mobile/Containers/Data/Application/33D7139A-53E0-4A2E-8C78-D3D13A2259B0/tmp/water-h2o-md.png 无法保存到已保存的相册:错误 域=AVFoundationErrorDomain 代码=-11828 "无法打开" UserInfo={NSUnderlyingError=0x1c0445d60 {错误 域=NSOSStatusErrorDomain 代码=-12847 "(null)"}, NSLocalizedFailureReason=不支持此媒体格式。, NSURL=file:///private/var/mobile/Containers/Data/Application/33D7139A-53E0-4A2E-8C78-D3D13A2259B0/tmp/water-h2o-md.png, NSLocalizedDescription=无法打开}

iOS 将图像视为视频?这是 iOS 上的错误还是我缺少什么。

更新

原来 Info.plist 文件中缺少下一个权限:

<key>NSPhotoLibraryUsageDescription</key>
<string>Application needs to access photos</string>

<!-- for iOS 11 -->
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Application needs to access photos</string>

现在 保存图像 操作正常。但严重的是,Apple 可能会返回Video image.jpg cannot be saved ... 更合适的错误

【讨论】:

    猜你喜欢
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 2021-05-05
    相关资源
    最近更新 更多