Flutter数据分块上传插件flutter_upchunk的使用

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

Flutter UpChunk

Flutter UpChunk 是由 MUX, Inc. 开发的 JavaScript 库 upchunk 的简单移植版本。

安装

pubspec.yaml 文件的 dependencies 部分添加以下内容:

dependencies:
  flutter_upchunk: ^2.0.2 # 或最新版本

使用

在需要使用 UpChunk.dart 文件中添加以下导入:

import 'package:flutter_upchunk/flutter_upchunk.dart';

示例

以下是一个完整的示例代码,展示了如何使用 flutter_upchunk 插件进行文件分块上传。这个示例允许用户从图库中选择一个视频文件并将其上传到指定的服务器端点。

import 'package:flutter/material.dart';
import 'package:flutter_upchunk/flutter_upchunk.dart';
import 'package:image_picker/image_picker.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'UpChunk Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'UpChunk Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({this.title = ''});

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 添加您的上传端点URL
  final _endPoint = 'https://your-upload-endpoint.com/upload';

  final picker = ImagePicker();

  int _progress = 0;
  bool _uploadComplete = false;
  String _errorMessage = '';

  void _getFile() async {
    final pickedFile = await picker.pickVideo(source: ImageSource.gallery);

    if (pickedFile == null) return;

    _uploadFile(pickedFile);
  }

  void _uploadFile(XFile fileToUpload) {
    _progress = 0;
    _uploadComplete = false;
    _errorMessage = '';

    UpChunk(
      endPoint: _endPoint,
      file: fileToUpload,
      onProgress: (double progress) {
        setState(() {
          _progress = progress.ceil();
        });
      },
      onError: (String message, int chunk, int attempts) {
        setState(() {
          _errorMessage = 'UpChunk error 💥 🙀:\n'
              ' - Message: $message\n'
              ' - Chunk: $chunk\n'
              ' - Attempts: $attempts';
        });
      },
      onSuccess: () {
        setState(() {
          _uploadComplete = true;
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (!_uploadComplete)
              Text(
                'Uploaded: $_progress%',
                style: TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.normal,
                ),
              ),
            if (_uploadComplete)
              Text(
                'Upload complete! 👋',
                style: TextStyle(
                  fontSize: 24,
                  color: Colors.green,
                  fontWeight: FontWeight.bold,
                ),
              ),
            if (_errorMessage.isNotEmpty)
              Text(
                _errorMessage,
                style: TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.normal,
                  color: Colors.red,
                ),
              ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _getFile,
        tooltip: 'Get File',
        child: Icon(Icons.upload_file),
      ),
    );
  }
}

API

虽然 API 是原 JavaScript 库的移植版本,但某些选项和属性略有不同。

UpChunk 构造函数

上传选项

  • endPoint 类型: string (必需)
    • 上传文件的 URL。
  • file 类型: XFile (必需)
    • 您要上传的文件。
  • headers 类型: Map<String, String>
    • 包含在每个分块的 PUT 请求中的任何头信息。
  • chunkSize 类型: integer,默认值: 5120
    • 将文件拆分成的分块大小(以 KB 为单位),最后一个分块可能更小。此参数应为 64 的倍数。
  • attempts 类型: integer,默认值: 5
    • 重试任何给定分块的次数。
  • delayBeforeRetry 类型: integer,默认值: 1
    • 在尝试重新上传分块之前等待的时间(以秒为单位)。
  • connectionCheckEndpoint 类型: String,默认值: null
    • 检查互联网连接的端点,如果为 null,则默认为 endPoint 中的 origin
  • chunkStart 类型: integer,默认值: null
    • 开始上传的分块编号,如果上传在第 x 个分块失败且对象实例丢失,UpChunk 可以从这里恢复上传。

事件选项

  • onAttempt { chunkNumber: Integer, chunkSize: Integer }
    • 在尝试上传分块之前立即触发。chunkNumber 是当前尝试的分块编号,chunkSize 是该分块的大小(以字节为单位)。
  • onAttemptFailure { message: String, chunkNumber: Integer, attemptsLeft: Integer }
    • 当尝试上传分块失败时触发。
  • onError { message: String, chunk: Integer, attempts: Integer }
    • 当分块达到最大重试次数或响应代码致命且暗示不应重试时触发。
  • onOffline
    • 当客户端离线时触发。
  • onOnline
    • 当客户端在线时触发。
  • onProgress progress double [0..100]
    • 连续触发,返回当前已上传文件的百分比。
  • onSuccess
    • 当上传成功完成时触发。

UpChunk 实例方法

  • pause()
    • 在当前飞行中的分块上传完成后暂停上传。
  • resume()
    • 恢复先前暂停的上传。
  • restart()
    • 从分块 0 重新开始上传,仅在 onError 被触发后使用
  • stop()
    • 立即取消上传。可以使用 restart() 从分块 0 重新开始上传。

致谢

原始代码由 MUX, Inc. 开发,并由一位 Flutter 开发者移植到 Dart 🎯 用❤️完成。


更多关于Flutter数据分块上传插件flutter_upchunk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据分块上传插件flutter_upchunk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用flutter_upchunk插件进行数据分块上传的示例代码。flutter_upchunk是一个帮助实现文件分块上传的Flutter插件,特别适合处理大文件上传的场景。

首先,确保你的Flutter项目已经添加了flutter_upchunk依赖。在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_upchunk: ^最新版本号 # 请替换为实际的最新版本号

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

接下来是一个完整的示例代码,展示了如何使用flutter_upchunk进行数据分块上传:

import 'package:flutter/material.dart';
import 'package:flutter_upchunk/flutter_upchunk.dart';
import 'dart:io';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UploadPage(),
    );
  }
}

class UploadPage extends StatefulWidget {
  @override
  _UploadPageState createState() => _UploadPageState();
}

class _UploadPageState extends State<UploadPage> {
  final Upchunk _upchunk = Upchunk();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter 数据分块上传示例'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _uploadFile,
          child: Text('上传文件'),
        ),
      ),
    );
  }

  Future<void> _uploadFile() async {
    // 选择文件
    FilePickerResult result = await FilePicker.platform.pickFiles(
      type: FileType.any,
    );

    if (result != null && result.files.isNotEmpty) {
      File file = File(result.files.first.path);

      // 获取文件信息
      int fileSize = file.lengthSync();
      int chunkSize = 1024 * 1024; // 1MB
      int totalChunks = (fileSize / chunkSize).ceil();

      // 配置上传URL和其他参数
      String uploadUrl = 'https://your-upload-endpoint.com/upload'; // 请替换为你的上传端点
      Map<String, String> headers = {
        'Authorization': 'Bearer your-token', // 请替换为你的认证token
      };

      // 上传文件
      for (int chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
        int start = chunkIndex * chunkSize;
        int end = min(start + chunkSize, fileSize);
        Uint8List chunkData = await file.readAsBytes(start, end - start);

        // 创建上传任务
        UpchunkUploadTask task = UpchunkUploadTask(
          url: uploadUrl,
          file: file,
          fileRange: Range(start, end - 1),
          totalChunks: totalChunks,
          chunkIndex: chunkIndex,
          headers: headers,
        );

        // 执行上传
        UpchunkUploadResult result = await _upchunk.upload(task);

        // 处理上传结果
        if (result.statusCode == 200) {
          print('Chunk ${chunkIndex + 1} uploaded successfully');
        } else {
          print('Failed to upload chunk ${chunkIndex + 1}: ${result.responseBody}');
          break; // 如果有需要,可以在失败时中断上传
        }
      }

      // 上传完成后的处理(如果需要)
      print('File upload completed');
    }
  }
}

注意事项:

  1. 文件选择器:示例中使用的是file_picker插件来选择文件。你需要在pubspec.yaml中添加file_picker依赖并运行flutter pub get来安装它。
  2. 上传端点:替换uploadUrl为你的实际上传端点。
  3. 认证:如果需要认证,替换headers中的Authorization值为你的实际token。
  4. 错误处理:在实际应用中,你可能需要更完善的错误处理和重试机制。

这个示例展示了如何分块读取文件并逐个上传,每个块上传后都会检查响应状态码以确定是否成功。如果某个块上传失败,你可以根据需要决定是否中断整个上传过程。

回到顶部