Flutter可恢复上传插件fp_resumable_uploads的使用

Flutter可恢复上传插件fp_resumable_uploads的使用

fp_resumable_uploads 插件提供了功能,可以将大视频文件分割成小块进行分块上传,并支持暂停和恢复上传。这对于确保在网络连接不稳定时的上传可靠性非常有用。

特性

  • 分块上传:将大视频文件分割成可管理的小块进行上传。
  • 可恢复上传:在遇到网络中断时,可以暂停并恢复上传。
  • 进度跟踪:通过自定义回调函数监控上传进度。
  • 错误处理:通过自定义回调函数优雅地处理错误。

安装

pubspec.yaml 文件中添加该包:

dependencies:
  fp_resumable_uploads: ^0.0.2

然后运行以下命令以获取该包:

flutter pub get

使用

导入包

import 'package:fp_resumable_uploads/flutter_resumable_uploads.dart';

暴露的方法

uploadVideo

此方法通过将视频文件分成小块并按顺序上传每个小块来启动上传过程。

参数:

  • file (File): 要上传的视频文件。
  • signedUrl (String): 获取每个块的签名URL的URL。
  • chunkSize (int?): 每个块的大小(默认为15MB)。
  • onProgress (Function?): 监控进度更新的回调函数。
  • onError (Function?): 处理错误的回调函数。

示例:

import 'dart:io';
import 'package:fp_resumable_uploads/flutter_resumable_uploads.dart';

void main() async {
  File videoFile = File('path_to_your_video_file.mp4');
  String signedUrl = 'your_signed_url';

  await FlutterResumableUploads.uploadVideo(
    file: videoFile,
    signedUrl: signedUrl,
    chunkSize: 15,
    onProgress: (progress) {
      print('Progress: $progress');
    },
    onError: (error) {
      print('Error: $error');
    },
  );
}

pauseUpload

暂停当前的上传过程。这在处理临时网络中断或用户发起的暂停时很有用。

示例:

FlutterResumableUploads.pauseUpload();

resumeUpload

从暂停处恢复先前的上传过程。

示例:

FlutterResumableUploads.resumeUpload();

示例使用

以下是一个完整的示例,演示如何使用 fp_resumable_uploads 包上传视频,并暂停/恢复上传。

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fp_resumable_uploads/flutter_resumable_uploads.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Resumable Uploads Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const UploadPage(),
    );
  }
}

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

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

class _UploadPageState extends State<UploadPage> {
  // 变量用于保存进度和错误信息
  String _status = '';
  int _currentChunkIndex = 0;
  int _totalChunks = 0;
  double _uploadPercentage = 0.0;
  String _errorMessage = '';

  @override
  void initState() {
    super.initState();
    // 监听进度更新
  }

  void _startUpload() async {
    try {
      final File file = 
          File('path/to/your/video.mp4'); // 替换为你自己的文件路径
      const String signedUrl = 
          'https://example.com/upload'; // 替换为你自己的签名URL

      await FlutterResumableUploads.uploadVideo(
        file: file,
        signedUrl: signedUrl,
        chunkSize: 10, // 可选:设置块大小(单位:MB)
        onProgress: (progress) {
          setState(() {
            _status = progress.status;
            _currentChunkIndex = progress.currentChunkIndex;
            _totalChunks = progress.totalChunks;
            _uploadPercentage = progress.uploadPercentage;
          });
        },
        onError: (error) {
          setState(() {
            _errorMessage = error.message;
          });
        },
      );
    } catch (e) {
      // 处理上传过程中可能出现的任何异常
      setState(() {
        _errorMessage = '发生意外错误: ${e.toString()}';
      });
    }
  }

  void _pauseUpload() {
    FlutterResumableUploads.pauseUpload();
    setState(() {
      _status = '已暂停';
    });
  }

  void _resumeUpload() {
    FlutterResumableUploads.resumeUpload();
    setState(() {
      _status = '已恢复';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('上传视频'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // 开始上传按钮
            ElevatedButton(
              onPressed: _startUpload,
              child: const Text('开始上传'),
            ),
            const SizedBox(height: 20),
            // 显示进度
            if (_status.isNotEmpty) ...[
              Text('状态: $_status'),
              Text('第 $_currentChunkIndex 块 / 共 $_totalChunks 块'),
              Text('上传进度: ${_uploadPercentage.toStringAsFixed(2)}%'),
            ],
            const SizedBox(height: 20),
            // 显示错误信息
            if (_errorMessage.isNotEmpty) ...[
              Text('错误: $_errorMessage', style: const TextStyle(color: Colors.red)),
            ],
          ],
        ),
      ),
    );
  }
}

测试

该插件包含一套测试用例,以确保其功能正常。你可以使用以下命令运行测试:

flutter test test/flutter_resumable_uploads_test.dart

更多关于Flutter可恢复上传插件fp_resumable_uploads的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


fp_resumable_uploads 是一个用于 Flutter 的可恢复上传插件,允许你在应用中进行文件上传,并且在上传中断后可以从断点继续上传。这对于上传大文件或网络不稳定的情况非常有用。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 fp_resumable_uploads 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  fp_resumable_uploads: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装插件。

基本用法

1. 导入插件

import 'package:fp_resumable_uploads/fp_resumable_uploads.dart';

2. 初始化上传

你需要指定上传的 URL、文件路径以及其他可选参数(如 headers、参数等)。

final uploader = ResumableUploader(
  url: 'https://your-upload-endpoint.com/upload',
  filePath: '/path/to/your/file.ext',
  headers: {
    'Authorization': 'Bearer your_token',
  },
  params: {
    'param1': 'value1',
    'param2': 'value2',
  },
);

3. 开始上传

你可以使用 startUpload 方法来开始上传。这个方法返回一个 Stream,你可以监听上传进度和状态。

uploader.startUpload().listen((uploadEvent) {
  if (uploadEvent is UploadProgress) {
    print('Upload progress: ${uploadEvent.progress}%');
  } else if (uploadEvent is UploadCompleted) {
    print('Upload completed!');
  } else if (uploadEvent is UploadError) {
    print('Upload failed: ${uploadEvent.error}');
  }
});

4. 暂停和恢复上传

你可以暂停上传,并在稍后恢复上传。

// 暂停上传
uploader.pauseUpload();

// 恢复上传
uploader.resumeUpload();

5. 取消上传

如果你不再需要上传,可以取消上传。

uploader.cancelUpload();

完整示例

以下是一个完整的示例,展示了如何使用 fp_resumable_uploads 插件进行文件上传:

import 'package:flutter/material.dart';
import 'package:fp_resumable_uploads/fp_resumable_uploads.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UploadScreen(),
    );
  }
}

class UploadScreen extends StatefulWidget {
  [@override](/user/override)
  _UploadScreenState createState() => _UploadScreenState();
}

class _UploadScreenState extends State<UploadScreen> {
  late ResumableUploader uploader;
  double progress = 0.0;

  [@override](/user/override)
  void initState() {
    super.initState();
    uploader = ResumableUploader(
      url: 'https://your-upload-endpoint.com/upload',
      filePath: '/path/to/your/file.ext',
      headers: {
        'Authorization': 'Bearer your_token',
      },
      params: {
        'param1': 'value1',
        'param2': 'value2',
      },
    );
  }

  void startUpload() {
    uploader.startUpload().listen((uploadEvent) {
      if (uploadEvent is UploadProgress) {
        setState(() {
          progress = uploadEvent.progress;
        });
      } else if (uploadEvent is UploadCompleted) {
        print('Upload completed!');
      } else if (uploadEvent is UploadError) {
        print('Upload failed: ${uploadEvent.error}');
      }
    });
  }

  void pauseUpload() {
    uploader.pauseUpload();
  }

  void resumeUpload() {
    uploader.resumeUpload();
  }

  void cancelUpload() {
    uploader.cancelUpload();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Resumable Upload Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Upload Progress: ${progress.toStringAsFixed(2)}%'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: startUpload,
              child: Text('Start Upload'),
            ),
            ElevatedButton(
              onPressed: pauseUpload,
              child: Text('Pause Upload'),
            ),
            ElevatedButton(
              onPressed: resumeUpload,
              child: Text('Resume Upload'),
            ),
            ElevatedButton(
              onPressed: cancelUpload,
              child: Text('Cancel Upload'),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部