Flutter大文件分块上传插件resumable_upload的使用

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

Flutter大文件分块上传插件resumable_upload的使用

resumable_upload 是一个由 PRO India 开发的 Flutter 插件,用于支持可恢复的大文件上传。它可以将大文件分割成多个块并上传到服务器,并在中断或失败时从断点继续上传。

最新版本

最新版本为 0.0.2

pro_resumable_upload

pro_resumable_upload 是一个 Flutter 包,它提供了支持可恢复文件上传的功能。你可以用它来将大文件上传到服务器,并且在遇到中断或失败时可以从中断处继续上传。

特性

  • 可恢复文件上传。
  • 支持大文件。
  • 轻松处理上传中断。
  • 配置上传行为的选项。

安装

  1. 在你的 pubspec.yaml 文件中添加 resumable_upload
dependencies:
    resumable_upload: ^1.0.0
  1. 导入包:
import 'package:pro_resumable_upload/pro_resumable_upload.dart';
  1. 创建一个 ResumableUpload 实例:
client = UploadClient(
  file: file,
  cache: _localCache,
  blobConfig: BlobConfig(blobUrl: blobUrl, sasToken: sasToken),
);
  1. 启动上传:
client!.uploadBlob(
  onProgress: (count, total, response) {
    // 处理进度更新
  },
  onComplete: (path, response) {
    // 处理完成更新
  },
);

配置选项

你可以通过设置以下可选参数来配置 ResumableUpload 的行为:

  • chunkSize: 设置每个块的大小,默认为 1 MB。
  • maxAttempts: 设置恢复上传的最大尝试次数,默认为 3 次。
  • headers: 添加自定义请求头,默认为空的 Map<String, String>
  • timeout: 设置每个上传请求的超时时间,默认为 60 秒。

示例代码

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:pro_resumable_upload/pro_resumable_upload.dart';

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '可恢复上传 Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: '可恢复上传 Demo 主页'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String process = '0%';
  late UploadClient? client;
  final LocalCache _localCache = LocalCache();

  _upload_func() async {
    final filePath = await filePathPicker();
    final File file = File(filePath!);
    const String blobUrl = '[BLOB-URL]';
    const String sasToken = '[SAS-TOKEN]';

    try {
      client = UploadClient(
        file: file,
        cache: _localCache,
        blobConfig: BlobConfig(blobUrl: blobUrl, sasToken: sasToken),
      );
      client!.uploadBlob(
        onProgress: (count, total, response) {
          final num = ((count / total) * 100).toInt().toString();
          setState(() {
            process = '$num%';
          });
        },
        onComplete: (path, response) {
          setState(() {
            process = 'Completed';
          });
        },
      );
    } catch (e) {
      setState(() {
        process = e.toString();
      });
    }
  }

  Future<String?> filePathPicker() async {
    File? file;

    try {
      final XFile? galleryFile = await ImagePicker().pickVideo(
        source: ImageSource.gallery,
      );

      if (galleryFile == null) {
        return null;
      }

      file = File(galleryFile.path);
    } catch (e) {
      return null;
    }

    return file.path;
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '$process',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(
              height: 20.0,
            ),
            InkWell(
              onTap: () {
                setState(() {
                  process = 'Cancelled';
                });
                client!.cancel();
              },
              child: Container(
                color: Colors.blueAccent,
                padding: const EdgeInsets.symmetric(
                    horizontal: 32.0, vertical: 16.0),
                child: const Text(
                  '取消',
                  style: TextStyle(
                      color: Colors.white, fontWeight: FontWeight.bold),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _upload_func,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter中使用resumable_upload插件进行大文件分块上传的示例代码。这个插件允许你将大文件分成小块并逐块上传到服务器,从而提高了上传的稳定性和可靠性。

首先,确保你已经在pubspec.yaml文件中添加了resumable_upload依赖:

dependencies:
  flutter:
    sdk: flutter
  resumable_upload: ^x.y.z  # 请替换为最新版本号

然后,在你的Flutter项目中,你可以按照以下步骤实现分块上传功能:

  1. 导入必要的库
import 'package:flutter/material.dart';
import 'package:resumable_upload/resumable_upload.dart';
import 'dart:io';
import 'dart:typed_data';
  1. 配置上传任务
void startUpload(File file) async {
  // 配置上传任务
  var uploadTask = ResumableUpload(
    url: 'https://your-server.com/upload',  // 替换为你的服务器上传URL
    file: file,
    chunkSize: 1024 * 1024,  // 每块大小,这里设置为1MB
    headers: {
      'Authorization': 'Bearer YOUR_ACCESS_TOKEN',  // 如果需要身份验证,请添加相应的头信息
    },
    onProgress: (progress) {
      // 上传进度回调
      print('上传进度: ${progress.percent}%');
    },
    onError: (error) {
      // 上传错误回调
      print('上传错误: $error');
    },
    onCompleted: () {
      // 上传完成回调
      print('上传完成');
    },
  );

  // 开始上传
  await uploadTask.start();
}
  1. 在UI中触发上传
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Resumable Upload Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              // 选择文件
              var filePickerResult = await FilePicker.platform.pickSingleFile();
              if (filePickerResult != null && filePickerResult.files.isNotEmpty) {
                var file = File(filePickerResult.files.single.path);
                // 开始上传
                startUpload(file);
              }
            },
            child: Text('选择文件并上传'),
          ),
        ),
      ),
    );
  }
}

请注意,上面的代码示例使用了file_picker插件来选择文件。你需要在pubspec.yaml中添加file_picker依赖:

dependencies:
  flutter:
    sdk: flutter
  resumable_upload: ^x.y.z  # 请替换为最新版本号
  file_picker: ^x.y.z  # 请替换为最新版本号

并且需要在代码中导入file_picker库:

import 'package:file_picker/file_picker.dart';

此外,还需要确保你的服务器能够处理分块上传的请求,并在收到所有块后正确地重组文件。服务器端的实现细节会根据你所使用的技术栈有所不同。

这个示例提供了一个基本的框架,你可以根据实际需求对其进行修改和扩展。

回到顶部