如何将pdf下载到移动设备 flutter

Ran*_*ric 3 dart flutter

您好,我有这个方法可以从 api 获取 pdf 并返回解码的文件,我可以在单击时显示它,但我想将其保存到设备。这是我解码pdf的方法:

  Future<File> _storeFile(String bytes) async {
    final filename = "${_dokument?.naziv}";
    final bytes = _dokument?.bytes;
    Uint8List base64Decode(String source) => base64.decode(source);

    await checkDocumentFolder();

    String dir = directory!.path;

    //final file = File('${dir.path}/$filename');
    final file = File('$dir/$filename');
    //var pdfBytes = bytes?.split(",")[1];
    if (!file.existsSync()) file.create();
    var pdfBytes = bytes?.substring(bytes.indexOf(",") + 1);
    print(pdfBytes);
    await file.writeAsBytes(base64Decode(pdfBytes!), flush: true);

    return file;
  }
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,我可以以某种方式将从该方法返回的文件保存到移动设备吗?

Wik*_*tor 9

有几件事需要考虑。

保存文件在不同设备上有所不同。对于 PDF 文件,我假设您希望用户能够轻松访问它们。为了实现这一点,它不能存储在应用程序的文件中 - 用户自己需要进行大量挖掘才能找到该文件。

它还需要多种权限,其中一些权限直接在特定于平台的文件中配置,另一些则必须在运行时向用户请求。权限处理程序包对于这项工作非常有用。

那么,这里是如何实现它:

import 'dart:io';

import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
Run Code Online (Sandbox Code Playgroud)

iOS

Future<void> saveFile(String fileName) async {
  var file = File('');

  // Platform.isIOS comes from dart:io
  if (Platform.isIOS) {
    final dir = await getApplicationDocumentsDirectory();
    file = File('${dir.path}/$fileName');
  }
Run Code Online (Sandbox Code Playgroud)

要使其在 iOS 上运行,您必须向ios/Runner/Info.plist文件添加 2 个密钥。

<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
Run Code Online (Sandbox Code Playgroud)

Android

if (Platform.isAndroid) {
  var status = await Permission.storage.status;
  if (status != PermissionStatus.granted) {
      status = await Permission.storage.request();
  }
  if (status.isGranted) {
      const downloadsFolderPath = '/storage/emulated/0/Download/';
      Directory dir = Directory(downloadsFolderPath);
      file = File('${dir.path}/$fileName');
  }
}
Run Code Online (Sandbox Code Playgroud)

另一方面,对于 Android,您还需要做更多的事情。

首先,需要compileSdkVersionandroid/app/build.gradle文件中进行正确设置。当我写这篇文章时 - 它应该设置为33.

android/app/src/main/AndroidManifest.xml正下方还需要 2 行manifest

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Run Code Online (Sandbox Code Playgroud)

当然,从代码中可以看出,我们还需要请求用户的许可。

Writing to the file

  // load file that you want to save on user's phone
  // it can be loaded from whenever you want, e.g. some API.
  final byteData = await rootBundle.load('assets/$fileName');
  try {
    await file.writeAsBytes(byteData.buffer
        .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
  } on FileSystemException catch (err) {
    // handle error
  }
}
Run Code Online (Sandbox Code Playgroud)

文件保存程序包将文件保存到应用程序的数据中,因此用户查找起来不会那么容易。它也是由未经验证的上传者发布的,所以我一定会记住它。