Flutter笔记:关于Flutter中的大文件上传(上)

这篇具有很好参考价值的文章主要介绍了Flutter笔记:关于Flutter中的大文件上传(上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Flutter笔记
关于Flutter中的大文件上传(上)
大文件上传背景与 Flutter 端实现文件分片传输

作者李俊才 (jcLee95):https://blog.csdn.net/qq_28550263
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/134302751


本系列上下两篇文章,包括 Flutter 端和 Django 端(后端)两个部分,讨论在 Flutter 端如何处理大文件,以及在 Django 端如何接收。


1. 概述

1.1 大文件上传的应用场景

在Flutter应用中,大文件上传的场景非常常见。例如,用户可能需要上传高清照片、视频或其他大型媒体文件。在企业应用中,用户可能需要上传大量的数据文件或报告。本文的主题是在Flutter应用中实现大文件上传。我们将探讨大文件上传的常见问题,介绍一些有效的上传策略,并提供实现这些策略的Flutter代码示例。我们的目标是帮助读者理解如何在Flutter应用中有效地上传大文件。

1.2 大文件上传的挑战

大文件上传面临许多挑战。首先,网络不稳定可能导致上传失败或速度慢。其次,由于文件大小,上传可能需要很长时间,而上传进度可能不明确,导致用户体验不佳。此外,如果应用在上传过程中崩溃或被关闭,可能需要从头开始上传,这会浪费大量时间和带宽。

1.3 整体上传局限性与优化策略

传统的文件上传方法通常是将整个文件作为一个请求体发送到服务器。然而,这种方法对大文件来说并不理想。由于网络不稳定,大文件有更大的可能性在上传过程中失败。此外,如果应用在上传过程中崩溃或被关闭,可能需要从头开始上传。

为了解决这些问题,我们可以采用一些策略来优化大文件的上传。

1.3.1 分块上传

例如,我们可以使用分块上传,将文件分成多个小块,然后分别上传。这样,即使某个块上传失败,也只需要重新上传该块,而不是整个文件。

1.3.2 断点续传

另一种策略是断点续传,它允许我们在上传被中断后从中断点继续上传,而不是从头开始。这两种策略各有优缺点。分块上传可以提高上传的成功率,但可能需要更复杂的服务器支持。断点续传可以节省带宽,但需要服务器支持范围请求,并且需要在客户端保存上传的进度。

2. 在Flutter中实现大文件上传前的准备

在这一章节中,我们将详细介绍如何在Flutter中实现大文件上传。我们将通过以下步骤来实现这个过程:获取权限、选择文件、分块、上传和处理错误。

2.1 获取权限

在用户选择文件之前,我们需要确保应用有读取文件的权限。我们可以使用permission_handler插件来请求权限。首先,需要在pubspec.yaml文件中添加permission_handler依赖以获取权限。

dependencies:
  permission_handler: 替换你安装的版本号

或者直接在项目中运行下面的命令安装最新版:

flutter pub add permission_handler

然后,我们可以使用Permission类的request方法来请求权限:

import 'package:permission_handler/permission_handler.dart';

void requestPermission() async {
  var status = await Permission.storage.status;
  if (!status.isGranted) {
    status = await Permission.storage.request();
  }
}

2.2 文件选择

在获取了权限后,我们可以使用file_picker插件来选择文件。首先,需要在pubspec.yaml文件中添加依赖:

dependencies:
  file_picker: 替换你安装的版本号

或者直接在项目中运行下面的命令安装最新版:

flutter pub add file_picker

然后,可以使用FilePicker的getFiles方法来选择文件:

import 'package:file_picker/file_picker.dart';

void pickFile() async {
  FilePickerResult? result = await FilePicker.platform.pickFiles();

  if(result != null) {
    PlatformFile file = result.files.first;
    print(file.name);
    print(file.bytes);
    print(file.size);
    print(file.extension);
    print(file.path);
  } else {
    // User canceled the picker
  }
}

3. 文件的切片

3.1 基本思路

在选择了文件后,我们需要将文件分块。分块的目的是将大文件切分成多个小块,这样我们可以逐个上传这些小块,而不是一次性上传整个大文件。这种方法有两个优点:

  1. 如果某个块上传失败,我们只需要重新上传该块,而不是整个文件;
  2. 我们可以更精确地追踪上传进度,因为我们可以知道已经上传了多少块和还剩下多少块。

3.2 实现步骤

在Flutter中,我们可以通过以下步骤来实现文件分块:

  1. 首先,我们需要 获取文件的字节数据
    我们可以使用 PlatformFile 对象的 bytes 属性来获取这些数据。这将返回一个 Uint8List 对象,它是一个包含文件所有字节的列表。

  2. 然后,我们需要 创建一个新的列表来存储分块的数据
    我们可以创建一个空的 List<int> 对象来存储这些数据。

  3. 接下来,我们需要 遍历文件的字节数据,并将数据分块
    我们可以使用一个循环来遍历字节数据。在每次迭代中,我们都会取出一块数据,并将这块数据添加到分块数据的列表中。

  4. 最后,返回分块数据的列表。

3.3 示范案例

一个具体的实现代码如下:

List<int> splitFile(PlatformFile file, int chunkSize) {
  List<int> chunks = [];
  List<int> bytes = file.bytes!.toList();
  for (int i = 0; i < bytes.length; i += chunkSize) {
    int end = (i + chunkSize < bytes.length) ? i + chunkSize : bytes.length;
    chunks.add(bytes.sublist(i, end));
  }
  return chunks;
}

其中,chunkSize 参数表示每个块的大小。

bytes.sublist(i, end) 方法用于获取从 iend 的子列表,这就是我们的一个块。

然后,将这个块添加到 chunks 列表中。这个过程会一直重复,直到所有的字节数据都被分块。

4. 切片的上传

在分块后,我们可以逐个上传这些块。在这个过程中,我们需要创建一个 HTTP 请求,将每个块作为请求的一部分,然后发送这个请求到服务器。我们可以使用 http库 来创建和发送 HTTP 请求。

以下是实现这个功能的步骤:

  1. 首先,我们需要创建一个 MultipartRequest 对象。
    这个对象表示一个 multipart/form-data 请求,它可以包含多个文件和其他类型的数据。我们需要指定请求的方法(在这个例子中是 POST )和 URL

  2. 然后,我们需要将块添加到请求中。
    我们可以使用 MultipartFile 类的 fromBytes 方法来创建一个文件对象,然后将这个对象添加到请求的 files 列表中。

  3. 接下来,我们需要发送请求。
    我们可以使用 send 方法来发送请求,这个方法会返回一个 StreamedResponse 对象。

  4. 最后,我们需要检查响应的状态码,以确定上传是否成功。
    如果状态码是 200,那么上传成功;否则,上传失败。

例如:

import 'package:http/http.dart' as http;

void uploadChunk(List<int> chunk, String url) async {
  var request = http.MultipartRequest('POST', Uri.parse(url));
  request.files.add(http.MultipartFile.fromBytes('file', chunk));
  var response = await request.send();
  if (response.statusCode == 200) {
    print('Uploaded!');
  } else {
    print('Failed to upload.');
  }
}

其中:
chunk 参数是我们要上传的块,url 参数是服务器的 URL
MultipartFile.fromBytes 方法的第一个参数是文件的名字,第二个参数是文件的字节数据;
send 方法会异步发送请求,所以我们需要使用 await 关键字来等待它完成。

5. 完整实现

作为Flutter端完整实现我简单写了一下,上传到了 Git Hub 上,并发布在 Pub.dev,地址为:https://pub.dev/packages/slivers_uploader。本文中各个交接讲解的仅仅是思路,而在该实现的版本中,做了诸多必要的调整。我将文件选择和上传分开。
一个Flutter端示例如下:

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

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

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'File Uploader Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final uploader = FileUploader(
    chunkSize: 50 * 1024 * 1024, // 指定分块大小,默认 1024*1024
  );

  MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('File Uploader Example'),
      ),
      body: Center(
        child: TextButton(
          child: const Text('Upload File'),
          onPressed: () async {
            var file = await uploader.pickFile();
            await file.upload(
              url: 'http://192.168.31.239:8001/upload/',
              onSuccess: (chunkNumber) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                      content: Text('Chunk $chunkNumber upload successful!')),
                );
              },
              onError: (chunkNumber) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Chunk $chunkNumber upload failed.')),
                );
              },
            );
          },
        ),
      ),
    );
  }
}


大概效果看起来是这样的:

flutter中大图片上传,Dart语言与Flutter框架开发笔记,前端、桌面端、移动端、UI、构建工具,Flutter,Dart,大文件,chunks,分块
在后端对应的可以看到通过POST发送过来的提交记录,就像我的后端这样:

flutter中大图片上传,Dart语言与Flutter框架开发笔记,前端、桌面端、移动端、UI、构建工具,Flutter,Dart,大文件,chunks,分块

下一篇文章,我们主要介绍 Django 后端如何实现对应的分块上传的文件。文章来源地址https://www.toymoban.com/news/detail-773489.html

到了这里,关于Flutter笔记:关于Flutter中的大文件上传(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue项目中大文件切片上传实现秒传、断点续传的详细实现教程

    在Vue项目中,大图片和多数据Excel等大文件的上传是一个非常常见的需求。然而,由于文件大小较大,上传速度很慢,传输中断等问题也难以避免。因此,为了提高上传效率和成功率,我们需要使用切片上传的方式,实现文件秒传、断点续传、错误重试、控制并发等功能,并

    2024年02月12日
    浏览(76)
  • 【前端面试】中大文件上传/下载:中等文件代理服务器放行+大文件切片传输+并发请求+localstorage实现断点续传

    目录 切片上传~spark-md5 原理:流式计算+分块处理 文件标识spark-md5:A-B A.切片哈希值合并 B.首尾切片+其他切片前中后各取2M 计算hash:A-B(参考React的Fiber架构) A.线程:web-worker B.空闲:requestIdleCallback 异步并发控制:A-B(参考http2的多路复用) A.promise.allSettled() B.并发数max=

    2024年02月12日
    浏览(56)
  • 【flutter上传图片】

    1.使用multi_image_picker插件 2.使用wechat_assets_picker插件 选择视频

    2024年02月10日
    浏览(36)
  • flutter 上传图片并裁剪

    1.首先在pubspec.yaml文件中新增依赖pub.dev image_picker: ^0.8.7+5 image_cropper: ^4.0.1 2.在Android的AndroidManifest.xml文件里面添加权限 3.在ios的Info.plist文件里面添加权限 项目根目录 4.代码实现

    2024年02月11日
    浏览(39)
  • flutter开发 - 七牛云上传sdk插件qiniu_flutter_sdk使用

    flutter七牛云上传sdk插件qiniu_flutter_sdk使用 最近在拆分代码,将上传组件设置成插件,下面记录下实现过程。 一、创建flutter_plugin上传插件 这里Android Studio使用创建plugin 填写一下信息 Project name Project location Description Project type Organization Android Language iOS Language Platforms 二、代码实

    2024年02月10日
    浏览(40)
  • 【flutter直接上传图片到阿里云OSS】

    flutter直接上传文件到阿里云需要获取凭证,通过调用阿里云获取凭证的接口能拿到下面这些参数 获取凭证的接口一般是后台去对接阿里云,前端调后台接口即可。(STS.的这种AccessKeyId安全性高一些) 1.获取OSSToken信息 token信息实体类 上传方法 调用方式 以上直接是上传图片到

    2024年02月11日
    浏览(39)
  • github上传超过100M的大文件

    当上传的工程中有超过100M的文件时,直接上传github会产生如下报错: 解决方法: 安装一个Git LFS(Git Large File Storge,Git 大文件储存) 先把其余文件正常上传,然后跟踪超过100M的文件, 有大文件一起上传push时要先清掉大文件的push缓存: 出现下面的进度条,就说明文件正在上

    2024年02月12日
    浏览(46)
  • flutter 客户端日志上传定位错误信息

    flutter 开发的app 安装到真机上 无法定位报错信息,只能使用usb连接电脑 使用adb logcat来查看日志效率低下。 如果将flutter 开发的app 运行的时候 将日志写进一个日志文件里面去,然后给flutter app搭建一个http服务器,后端知道对应app的ip后,直连对应app 获取日志文件。 获取本机

    2024年01月21日
    浏览(41)
  • 关于flutter中 initState() 与 setState() 用法

    initState() 函数是在组件渲染之前执行的。在Flutter中, initState() 是 StatefulWidget 的生命周期方法之一,在调用 build() 方法之前被调用。 当创建一个 StatefulWidget 并将其添加到组件树中时,Flutter会实例化该组件的状态对象,并在调用 initState() 方法后再调用 build() 方法来构建UI。

    2024年02月11日
    浏览(38)
  • Flutter 笔记 | Flutter 动画

    为了方便开发者创建动画,不同的UI系统对动画都进行了一些抽象, Flutter中也对动画进行了抽象,主要涉及 Animation、Curve、Controller、Tween 这四个角色,它们一起配合来完成一个完整动画,下面我们一一来介绍它们。 1. Animation Animation 是一个抽象类,它本身和UI渲染没有任何关

    2024年02月07日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包