Flutter加载本地pdf文件

通过flutter预览本地的pdf文件,选了多个flutter插件后最终选择了pdfx,

首先看一下我的需求吧,左侧是所有的文件列表右侧是文件的内容,左侧比较简单我们读取指定的目录后将文件名显示出来,点击选中时候切换文件显示

 说说实现过程吧,首先是通过flutter读取本地的文件夹目录,通过path_provider插件读取本地文件目录

  /**
   * 获取本地目录getExternalStorageDirectory()
   * /storage/emulated/0/Android/data/com.example.read_database/files
   * 通过list获取的是包含文件夹的
   */
  static Future<Stream<FileSystemEntity>?> getLocalPdfFile() async {
    var externalStoragePath = await getExternalStorageDirectory();
    var dis = Directory('${externalStoragePath?.path}/mipdf/');
    if (dis.existsSync()) {
      return dis
          .list(recursive: true)//过滤文件,不显示文件夹
          .where((event) => FileSystemEntity.isFileSync(event.path));
    } else {
      dis.create();
      return null;
    }
  }
具体实现代码如下
class MuBiaoZiYuanBody extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MuBiaoZiYuanBodyState();
}

class MuBiaoZiYuanBodyState extends State<MuBiaoZiYuanBody> {
  List<FileSystemEntity>? _stream;
  int _itemCount = 0;
  int _selected = 0;
  //Android 和ios用 PdfControllerPinch window用PdfController
  PdfControllerPinch? _controller;
  @override
  void initState() {
    _initData();
    super.initState();
  }

  /// 初始化数据
  Future<void> _initData() async {
    _stream = await (await ReadFileUtil.getLocalPdfFile())?.toList();
    int length = (_stream?.length)!;
    _controller = PdfControllerPinch(
      document: PdfDocument.openFile(
        _stream![0].uri.toFilePath(windows: false),
      ),
    );
    setState(() {
      _itemCount = length;
    });
  }


  Future<void> _ChangePdf(int path) async {
    //注意此处不可重新初始化,否则会出现刷新切换不了文件,实现不出来
    // PdfControllerPinch(
    //       document: PdfDocument.openFile(
    //         _stream![0].uri.toFilePath(windows: false),
    //       ),
    //     )
    //
    _controller?.loadDocument(
        PdfDocument.openFile(_stream![path].uri.toFilePath(windows: false)!));
    setState(() {
      _selected = path;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Row(
        children: [
          _buildListFile(),
          Expanded(
            flex: 1,
            child: Container(
              padding: const EdgeInsets.only(
                  left: 4, top: 10, bottom: 10, right: 10),
              // child: PdfPreViewWidget(path: _selectFilePath),
              // child: PdfxWidget(path:'assets/kotlin.pdf'),
              child: (_controller == null)
                  ? const Center(
                      child: Text("正在加载"),
                    )
                  : buildPdfViewPinch(),
            ),
          )
        ],
      ),
    );
  }

  Container _buildListFile() {
    return Container(
          width: 182,
          padding:
              const EdgeInsets.only(left: 4, top: 10, bottom: 10, right: 10),
          child: ListView.separated(
            separatorBuilder: (BuildContext context, int index) =>
                const Divider(
              color: Colors.transparent,
              height: 10,
            ),
            itemCount: _itemCount,
            itemBuilder: (context, index) {
              return _buildItem(index, context);
            },
          ),
        );
  }

  PdfViewPinch buildPdfViewPinch() {
    return PdfViewPinch(
      controller: _controller!,
      builders: PdfViewPinchBuilders<DefaultBuilderOptions>(
        options: const DefaultBuilderOptions(
            loaderSwitchDuration: Duration(milliseconds: 300)),
        documentLoaderBuilder: (_) =>
            Center(child: LoadingDialog(text: "加载文档")),
        pageLoaderBuilder: (_) => Center(child: LoadingDialog(text: "加载页")),
        errorBuilder: (_, error) => Center(child: Text(error.toString())),
      ),
    );
  }

  Widget _buildItem(int index, BuildContext context) {
    var path = _stream?[index].path;
    return ElevatedButton(
      onPressed: () async {
        _ChangePdf(index);
      },
      style: ButtonStyle(
        padding: MaterialStateProperty.all(const EdgeInsets.all(15)),
        backgroundColor: MaterialStateProperty.all(
            _selected == index ? Color(0xfff8b651) : Colors.white),
        elevation: MaterialStateProperty.all(4),
      ),
      child: Text(
        basename(path!),
        style: const TextStyle(
            color: MyColor.textColor,
            fontWeight: FontWeight.bold,
            fontSize: 16),
      ),
    );
  }
}

此处需要避坑:

避坑1:

        在change时候,就是重新加载一个新的文件的时候,我们只需要用controller重新loadDocument即可,不可以重新初始化,会出现加载不出来的情况。

_controller?.loadDocument(
    PdfDocument.openFile(_stream![path].uri.toFilePath(windows: false)));

避坑2:openFile(String path),这里的蚕食我们要用,不可以直接传入_stream![path]

_stream![path].uri.toFilePath(windows: false)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Flutter中上传本地文件,您需要使用Flutter中提供的dart:io库。首先,使用FilePicker库选择要上传的文件。然后,使用http包中的MultipartRequest,将文件作为多部分请求附加到请求体中。最后,使用http包中的HttpClient将请求发送到服务器。以下是一个示例代码: ```dart import 'dart:io'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; class FileUpload extends StatefulWidget { @override _FileUploadState createState() => _FileUploadState(); } class _FileUploadState extends State<FileUpload> { File file; void _openFileExplorer() async { file = await FilePicker.getFile(type: FileType.any); setState(() {}); } Future _uploadFile() async { var request = http.MultipartRequest( 'POST', Uri.parse('your-upload-api-url-here'), ); request.files.add(await http.MultipartFile.fromPath('file', file.path)); request.headers.addAll({'Authorization': 'Bearer your_access_token_here'}); var response = await request.send(); if (response.statusCode == 200) { // handle success } else { // handle error } } @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ FlatButton( onPressed: _openFileExplorer, child: Text('Select File'), ), file != null ? Text(file.path) : Container(), RaisedButton( onPressed: _uploadFile, child: Text('Upload File'), ), ], ); } } ``` 您需要将“your-upload-api-url-here”替换为您的上传API的实际URL,“Bearer your_access_token_here”替换为您的实际访问令牌。此外,您需要在pubspec.yaml文件中添加依赖项file_picker和http。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值