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.')),);},);},),),);}
}

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

在这里插入图片描述
在后端对应的可以看到通过POST发送过来的提交记录,就像我的后端这样:

在这里插入图片描述

下一篇文章,我们主要介绍 Django 后端如何实现对应的分块上传的文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab模糊控制文件m代码实现和基础理论

1、内容简介 略 15-可以交流、咨询、答疑 通过m代码来实现生成模糊文件fis文件 2、内容说明 模糊文件m代码实现和基础理论 matlab模糊控制文件m代码实现和基础理论 模糊文件、m代码和模糊基础理论 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.co…

Sui学术研究奖公布,资助研究者探索人工智能、能源市场和区块链游戏

Sui基金会高兴地宣布首轮Sui学术研究奖&#xff08;SARAs&#xff09;的获奖者。SARAs计划提供资助&#xff0c;支持推动Sui区块链技术的研究。学术和研究界对我们的初次征集呈现出大量高质量的提案。 已接受的九个提案涵盖了各种主题&#xff0c;如token经济学、智能合约机制…

docker stop slow 解决

验证 NanoMQ stop slow 的问题 daemon 和非 daemon 两种方式 docker stop 都很慢 疑问是默认情况下&#xff0c;SIGTERM 会被处理。 模拟 docker 内发送 SIGTERM 信号 # The default signal for kill is TERM # pkill will send the specified signal (by defau…

开发知识点-Django

Django 1 了解简介2 Django项目结构3 url 地址 和视图函数4 路由配置5 请求及响应6 GET请求和POST请求查询字符串 7 Django设计模式及模板层8 模板层-变量和标签9 模板层-过滤器和继承继承 重写 10 url反向解析11 静态文件12 Django 应用及分布式路由创建之后 注册 一下 13 模型…

matlab直线一级倒立摆lqr控制

1、内容简介 略 16-可以交流、咨询、答疑 matlab直线一级倒立摆lqr控制 2、内容说明 倒立摆是一个开环不稳定的强非线性系统&#xff0c;其控制策略与杂技运动员顶杆平衡表演的技巧有异曲同工之处&#xff0c;目的在于使得摆杆处于临界稳定状态&#xff0c;是进行控制理论研…

MySQL的SQL预编译及防SQL注入

文章目录 1 SQL语句的执行处理1.1 即时SQL1.2 预处理SQL1.2.1 预编译SQL的实现步骤1.2.2 预编译SQL的C使用举例1.2.3 MYSQL_BIND()函数中的参数类型&#xff1a; 2 SQL注入2.1 什么是SQL注入2.2 如何防止SQL注入 1 SQL语句的执行处理 SQL的执行可大致分为下面两种模式&#xf…

python双端队列_中间是头两边是尾_两边是头中间是尾

双端队列的顺序表存储结构以及两种特殊的双端队列 双端队列 是一种允许我们同时从前端和后端添加和删除元素的特殊队列&#xff0c;它是队列和栈的结合体。 双端队列&#xff08;deque&#xff09;与队列&#xff08;queue&#xff09;就差了两个字&#xff0c;队列里元素只能…

使用Redis实现热搜功能

Redis热搜 原理数据类型redis操作简单实现 实操封装方法执行方法最后使用springboot的定时任务对热搜榜单进行维护 原理 使用redis实现热搜的原理就是维护一个zset集合&#xff0c;然后使用score作为当前搜索词的搜索量&#xff0c;score越高的搜索词就说明该搜索词热度越高。…

css实战——清除列表中最后一个元素的下边距

需求描述 常见于列表的排版&#xff0c;如文章列表、用户列表、商品列表等。 代码实现 <div class"listBox"><div class"itemBox">文章1</div><div class"itemBox">文章2</div><div class"itemBox"…

SSM框架Demo: 简朴博客系统

文章目录 1. 前端页面效果2. 项目创建3. 前期配置3.1. 创建数据库数据表3.2. 配置文件 4. 创建实体类5. 统一处理5.1. 统一返回格式处理5.2. 统一异常处理 6. 全局变量7. Session工具类8. 登录拦截器9. 密码加盐加密10. 线程池组件11. dao层11.1. UserMapper11.2. ArticleMappe…

nodejs express vue uniapp电影购票系统源码

开发技术&#xff1a; node.js&#xff0c;vscode&#xff0c;HBuilder X express vue elementui uniapp 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示搜索电影&#xff0c;轮播图&#xff0c;电影分类&#xff0c;最近上架电影 点击电影进入电影详情&am…

数据结构线性表——栈

前言&#xff1a;哈喽小伙伴们&#xff0c;今天我们将一起进入数据结构线性表的第四篇章——栈的讲解&#xff0c;栈还是比较简单的哦&#xff0c;跟紧博主的思路&#xff0c;不要掉队哦。 目录 一.什么是栈 二.如何实现栈 三.栈的实现 栈的初始化 四.栈的操作 1.数据入栈…

Apache Druid连接回收引发的血案

问题 线上执行大批量定时任务&#xff0c;发现SQL执行失败的报错&#xff1a; CommunicationsException, druid version 1.1.10, jdbcUrl : jdbc:mysql://xxx?useUnicodetrue&characterEncodingUTF-8&zeroDateTimeBehaviorconvertToNull,testWhileIdle true, idle …

Zigbee智能家居方案设计

背景 目前智能家居物联网中最流行的三种通信协议&#xff0c;Zigbee、WiFi以及BLE&#xff08;蓝牙&#xff09;。这三种协议各有各的优势和劣势。本方案基于CC2530芯片来设计&#xff0c;CC2530是TI的Zigbee芯片。 网关使用了ESP8266CC2530。 硬件实物 节点板子上带有继电器…

Hosts File Editor 实用工具

我一般手工编辑hosts文件&#xff0c;我想给hosts文件加一个开关&#xff0c;本想自己实现&#xff0c;但是忽然发现微软已经提供了官方的解决方案&#xff0c;感觉有能人。 对文件的行的修改被抽象成了一个开关。腻害&#xff01;&#xff01;&#xff01;

◢Django 自写分页与使用

目录 1、设置分页样式,并展示到浏览器 2、模拟页码 3、生成分页 4、数据显示 5、上一页下一页 6、数据库的数据分页 7、封装分页 8、使用封装好的分页 建立好app后&#xff0c;设置路径path(in2/,views.in2)&#xff0c;视图def in2(request): &#xff0c;HTML: in2.html…

RK3568笔记五:基于Yolov5的训练及部署

若该文为原创文章&#xff0c;转载请注明原文出处。 一. 部署概述 环境&#xff1a;Ubuntu20.04、python3.8 芯片&#xff1a;RK3568 芯片系统&#xff1a;buildroot 开发板&#xff1a;ATK-DLRK3568 开发主要参考文档&#xff1a;《Rockchip_Quick_Start_RKNN_Toolkit2_C…

开源知识库软件xwiki在Windows下的安装

文章目录 开源知识库软件-xwiki在windows上的部署0、参考文档1、前置环境准备1.1、Windows版本及系统配置1.2、JDK11安装1.3、Tomcat9安装1.4、MySQL5.7数据库的安装 2、xwiki安装3、配置3.1、修改配置支持对文档内容进行搜索 4、问题解决4.1、附件无法上传问题4.1、附件无法下…

FreeRTOS知识梳理

一、RTOS:Real time operating system,中文意思为 实时操作系统&#xff0c;它是一类操作系统&#xff0c;比如uc/OS、FreeRTOS、RTX、RT-Thread 这些都是实时操作系统。 二、移植FreeRTOS到STM32F103C8T6上 interface选择CMSIS_V1,RCC选择Crystal Ceramic Resonator 。 …

海康威视(iVMS)综合安防系统任意文件上传漏洞复现 [附POC]

文章目录 海康威视&#xff08;iVMS&#xff09;综合安防系统任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 海康威视&#xff08;iVMS&#xff09;综合安防系统任意文件上传漏洞复…