likes
comments
collection
share

Flutter下载文件并使用原生打开

作者站长头像
站长
· 阅读数 38

下载文件

想要在Flutter下载文件,可以使用Dio网络请求库,Dio中有download函数, 定义如下:

Future<Response> download(
  String urlPath,
  savePath, {
  ProgressCallback? onReceiveProgress,
  Map<String, dynamic>? queryParameters,
  CancelToken? cancelToken,
  bool deleteOnError = true,
  String lengthHeader = Headers.contentLengthHeader,
  data,
  Options? options,
});

  • urlPath:网络资源的 url

  • savePathdynamic 类型,可以是下载后存储文件路径的字符串,也可以是一个返回字符串的回调方法(Dio 会把 headers 参数携带过去,方便针对下载返回内容构建文件路径);

  • onReceiveProgress:文件接收进度,是一个void Function(int count, int total)回调函数,调用者可以通过该回调方法监测下载进度。

  • deleteOnError:发生错误时候是否删除已下载的文件,默认是 true。

  • lengthHeader:源文件的实际大小(未压缩前)。默认是 headercontent-length。如果文件压缩了,而没有指定该值的话,那进度回调里的total会是-1;如果使用自定义的 header 指定了文件的大小,那么total会是自定义的 header 对应的文件大小。

  • 其他参数和普通的请求差不多,这里不再赘述。

使用此函数即可进行下载文件

获取保存文件路径

可以使用path_provider库获取保存文件的路径,path_provider 提供了如下方法:

  • getTemporaryDirectory:应用临时目录(可能被清除)
  • getApplicationDocumentsDirectory:应用文档目录(不会被系统清除,主要用户数据存储目录),对于安卓推荐使用外部存储getExternalStorageDirectory。
  • getApplicationSupportDirectory:应用支持目录,一般放置与用户无关的数据。
  • getLibraryDirectory:指向应用可以持久存储数据的目录,不支持安卓平台。
  • getExternalStorageDirectory:获取外部存储目录,不支持 iOS 平台。
  • getExternalCacheDirectories:获取外部缓存目录,,不支持 iOS 平台。
  • getExternalStorageDirectories:获取外部可以的目录列表,不支持 iOS 平台。
  • getDownloadsDirectory:获取下载目录,用于 Web 端,不支持安卓和 iOS平台。

通过 path_provider拿到Directory对象后,就可以通过 Directorypath 属性获取到完整的目录路径。本例我们是在 initialState 里获取文件存储路径的,使用的是应用文档目录。

void initState() {
  getApplicationDocumentsDirectory()
      .then((tempDir) => {_destPath = tempDir.path + '/zakiFlutter.docx'});

  super.initState();
}

下载文件时安卓需要获取写入的权限

我使用的是permission_handler权限管理库,代码如下

/// 申请写文件权限
    final status = await Permission.storage.request();

    switch (status) {
      case PermissionStatus.granted:
        break;
      case PermissionStatus.denied:
        HUDTools.showMessage('拒绝访问存储权限');
        break;
      case PermissionStatus.permanentlyDenied:
        showXmDialog(
          title: '提示',
          content: '存储投稿模版需要打开存储权限,是否进入设置界面开启?',
          cancelText: '取消',
          confirmText: '去开启',
          onConfirmTap: () => AppSettings.openAppSettings(),
        );
        break;
      default:
        break;
    }

需要注意的是,要在.android -> app -> src -> main -> AndroidManifest.xml 中增加读写权限

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

下载本地后在iOS预览或者使用其他应用打开

Flutter有第三方库 open_filex 可以进行上述操作,但是安卓同事在运行过程中异常,所以暂时先用flutter传递消息后,在原生进行处理的方式进行。

在iOSApp中预览文件时需要使用到UIDocumentInteractionController这个控制器,官方释义如下

A view controller that previews, opens, or prints files whose file format cannot be handled directly by your app. 

一个view controller可以用来预览,打开或者打印,不能被你的app直接处理的文件

将需要打开文件的信息发送至原生后的处理,代码如下

let ctr = UIDocumentInteractionController()

func openFile() {

    let url = Bundle.main.path(forResource: "zakiFlutter", ofType: "docx")

    ctr.url = URL(fileURLWithPath: enterURL)
    ctr.delegate = self

    ///预览方法
    ctr.presentPreview(animated: true)
    
    ///分享方法
    ctr.presentOptionsMenu(from: self.view.bounds, in: self.view, animated: true)
}



extension zakiFlutterViewController: UIDocumentInteractionControllerDelegate {
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }
}

注意:使用分享方法分享文件时,需要将controller放到class里持有,否则分享时会为空或者报错

总结

需要在iOS原生文件app中展示时,在Info.plist中 新增 Supports Document Browser 为 YES。

需要在iTunes中分享时展示,在Info.plist新增 Application supports iTunes file sharing 为YES

转载自:https://juejin.cn/post/7184732401158291511
评论
请登录