Flutter网页文件选择插件flutter_web_file_selector的使用

发布于 1周前 作者 caililin 来自 Flutter

Flutter网页文件选择插件flutter_web_file_selector的使用

插件简介

flutter_web_file_selector 是一个Flutter包,旨在让用户在Web平台上选择文件。它特别设计用于解决iOS/iPadOS浏览器上文件选择弹出菜单位置不合理的问题。如果你遇到并被这个问题困扰,可以使用这个包来解决。虽然此包可以在所有Web平台上使用,但建议对于非iOS Web平台使用其他更受欢迎且经过验证的包如 file_pickerfile_selector 。我将 flutter_web_file_selector 视为一种临时解决方案,直到这些流行包解决了上述问题。

Before

功能特性

你可能遇到过iOS/iPadOS浏览器上的文件选择弹出菜单定位不准确的情况。使用此包后,弹出菜单将会正确地显示在你点击的位置旁边。

使用方法

要使用此包,请将 flutter_web_file_selector 添加为 pubspec.yaml文件中的依赖项。

示例代码

下面是一个完整的示例demo,展示了如何在项目中使用 flutter_web_file_selector 包。

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_web_file_selector/flutter_web_file_selector.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _disabled = false;

  Future<void> _processFiles(List<XFile> files) async {
    for (final XFile file in files) {
      debugPrint('File: ${file.name} (MIME type: ${file.mimeType})');

      // You can get bytes from the file with these methods:
      // final Uint8List bytes = await file.readAsBytes();
      // final Stream<Uint8List> stream = file.openRead();
      // ...
    }
  }

  Future<void> _selectFiles() {
    return showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: const Text('Not using flutter_web_file_selector'),
          content: const Text(
            'You can use other packages like file_selector or file_picker',
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text('Close'),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    // To use the flutter_web_file_selector package on all web browsers, you can just use kIsWeb.
    const bool useWebFileSelector = kIsWeb;
    // To use the package only for web browsers running on iOS/iPadOS, you can use WebFileSelector.isIOSWeb instead.
    // final useWebFileSelector = WebFileSelector.isIOSWeb;

    // The "accept" argument in WebFileSelector accepts the same value as the accept attribute in <input type="file">.
    // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept
    const String acceptedFileTypes = '.pdf, .png, .jpg, .jpeg, .tif, .tiff';

    // The "multiple" aregument controls whether to let users select multiple files or not.
    const bool multipleFiles = true;

    // onPress event handler for buttons
    void Function()? onPressed;
    if (!_disabled) {
      onPressed = () {
        if (!useWebFileSelector) {
          // Not using the WebFileSelector.
          // Use other packages like file_selector or file_picker.
          _selectFiles();
        }
      };
    }

    // onData event handler for WebFileSelector widget
    void Function(List<XFile> files)? onData;
    if (!_disabled) {
      onData = (files) => _processFiles(files);
    }

    // Create a "Select Files" button
    Widget selectFilesButton = ElevatedButton(
      onPressed: onPressed,
      child: const Text('Select Files'),
    );

    if (useWebFileSelector) {
      // Wrap the "Select Files" button with WebFileSelector widget
      selectFilesButton = WebFileSelector(
        onData: onData,
        accept: acceptedFileTypes,
        multiple: multipleFiles,
        child: selectFilesButton,
      );
    }

    // Create a floating action button
    Widget? floatingActionButton;
    if (!_disabled) {
      floatingActionButton = FloatingActionButton(
        onPressed: onPressed,
        tooltip: 'Select Files',
        child: const Icon(Icons.add),
      );

      if (useWebFileSelector) {
        // Wrap the floating action button with WebFileSelector widget
        floatingActionButton = WebFileSelector(
          onData: onData,
          accept: acceptedFileTypes,
          multiple: multipleFiles,
          child: floatingActionButton,
        );
      }
    }

    // Create a "Enable/Disable Buttons" button
    final toggleButton = ElevatedButton(
      onPressed: () => setState(() {
        // Toggle the Enable/Disable button
        _disabled = !_disabled;
      }),
      child: Text(_disabled ? 'Enable Buttons' : 'Disable Buttons'),
    );

    // Put them together
    return Scaffold(
      appBar: AppBar(
        title: const Text('flutter_web_file_selector Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('Press one of the buttons to select files'),
            const SizedBox(height: 10),
            selectFilesButton, // "Select Files" button
            const SizedBox(height: 20),
            toggleButton, // "Enable/Disable Buttons" button
          ],
        ),
      ),
      floatingActionButton: floatingActionButton, // Floating action button
    );
  }
}

该示例演示了如何根据是否是iOS Web环境来决定是否使用 flutter_web_file_selector 包,并且展示了如何处理文件选择后的数据。你可以根据自己的需求调整 acceptedFileTypesmultipleFiles 参数以适应不同的文件选择需求。


更多关于Flutter网页文件选择插件flutter_web_file_selector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网页文件选择插件flutter_web_file_selector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter Web项目中使用flutter_web_file_selector插件来选择文件的示例代码。这个插件允许你在Flutter Web应用中让用户选择文件,并获取文件的详细信息。

首先,确保你已经将flutter_web_file_selector插件添加到你的pubspec.yaml文件中:

dependencies:
  flutter:
    sdk: flutter
  flutter_web_file_selector: ^0.x.x  # 请使用最新版本号

然后,运行flutter pub get来安装依赖。

接下来,是一个完整的示例代码,展示如何使用flutter_web_file_selector来选择文件并显示文件信息:

import 'package:flutter/material.dart';
import 'package:flutter_web_file_selector/flutter_web_file_selector.dart';
import 'dart:html' as html;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Web File Selector Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: FileSelectorScreen(),
    );
  }
}

class FileSelectorScreen extends StatefulWidget {
  @override
  _FileSelectorScreenState createState() => _FileSelectorScreenState();
}

class _FileSelectorScreenState extends State<FileSelectorScreen> {
  List<html.File> _selectedFiles = [];

  Future<void> _selectFiles() async {
    try {
      final List<html.File> files = await FlutterWebFileSelector.instance.openFileDialog(
        accept: {
          'image/*': ['.png', '.jpg', '.jpeg', '.gif'],
          'text/plain': ['.txt'],
        },
        multiple: true,
      );

      setState(() {
        _selectedFiles = files;
      });
    } catch (e) {
      print('Error selecting files: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Web File Selector Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _selectFiles,
              child: Text('Select Files'),
            ),
            SizedBox(height: 20),
            if (_selectedFiles.isNotEmpty)
              Column(
                children: _selectedFiles.map((file) {
                  return ListTile(
                    title: Text(file.name),
                    subtitle: Text('Size: ${(file.size / 1024).toStringAsFixed(2)} KB'),
                  );
                }).toList(),
              ),
          ],
        ),
      ),
    );
  }
}

代码说明:

  1. 依赖导入

    • 导入flutterflutter_web_file_selector包。
    • 导入dart:html包以便访问HTML相关的功能。
  2. 主应用

    • 使用MaterialApp构建主应用,并设置主页为FileSelectorScreen
  3. 文件选择界面

    • FileSelectorScreen是一个有状态的Widget,用于管理文件选择的状态。
    • _selectedFiles列表用于存储用户选择的文件。
  4. 选择文件功能

    • _selectFiles方法使用FlutterWebFileSelector.instance.openFileDialog来打开文件选择对话框。
    • accept参数指定了可以接受的文件类型(例如,图像文件和文本文件)。
    • multiple参数设置为true,允许用户选择多个文件。
  5. UI展示

    • 使用ElevatedButton来触发文件选择功能。
    • 如果用户选择了文件,则使用ColumnListTile来展示每个文件的名称和大小。

运行应用:

确保你在Flutter的Web环境下运行这个应用,可以使用以下命令:

flutter run -d chrome

这将启动Chrome浏览器并加载你的Flutter Web应用。在浏览器中,你可以点击“Select Files”按钮来选择文件,并在界面上看到所选文件的详细信息。

回到顶部