前端-关于apk文件分片上传

article/2025/8/21 10:52:12

为什么需要分片上传?

一次性处理的致命缺陷:
  • 内存溢出:大文件完全加载到内存

  • 界面冻结:读取过程阻塞主线程

  • 上传失败:单次请求可能超时或被服务器拒绝

需求:一个弹出框,将apk文件上传,显示进度条,上传完毕显示基本信息(比如apk名称,大小点),点击“确定”按钮上传到后端

1、解析apk文件,获得一些基本信息,需要第三方库 App-Info-Parser 

2、有的apk文件很大,需要分片上传

3、具体上传的地点:本项目是对象存储,因此只需要调用对象存储的方法;如果不用对象存储,可以考虑第三方库,比如 simple-uploader.js (同事用过)

html中引入第三方库,挂载在window对象上

  <script src="/AppInfoParser.js"></script>

 vue组件

import { uploadFile } from '../components/uploadFile.js'
/*** 解析apk文件* @param file*/
const parseApk = async file => {let resulttry {result = await new window.AppInfoParser(file).parse()if (result) {//通过result获得apk信息,比如应用包名、版本号等,省略// 解析完成后上传文件,分片上传uploadFileMethod()}} catch (e) {if (result && (!result.application.label || result.application.label.length <= 0)) {proxy.$warningTip('获取应用名失败')} else {proxy.$warningTip('解析失败,请重试')}console.log('解析apkFile失败', e)}
}
const fileBuffer = ref([])
let fileLength = ref(1) //原始分片数
let taskComplete = ref(1) //已完成上传的分片数/*** 上传文件*/
const uploadFileMethod = async () => {// 文件分片fileBuffer.value = await uploadFile(file.value, 5 * 1024 * 1024)fileLength.value = fileBuffer.value.length
}

 uploadFile.js 文件

export const uploadFile = async (file, chunkSize = 8 * 1024 * 1024) => {let buffersArray = await getFileChunk(file, chunkSize)return buffersArray
}/*** 获取文件分块成二维数组的buffer* @param {*} file 需要分块的文件* @param {*} chunkSize 一块大小,默认为8M(8 * 1024 * 1024)* @returns*/
const getFileChunk = (file, chunkSize) => {return new Promise(resovle => {//兼容性处理,目的是在不同浏览器中安全地获取文件切割方法let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,//向上取整,确保最后一片不足 chunkSize 的部分也能被处理chunks = Math.ceil(file.size / chunkSize),currentChunk = 0,fileReader = new FileReader(),buffers = []//每次读取一个分片就会触发一次`onload`事件fileReader.onload = function (e) {const chunk = e.target.result //一个分片大小,是一个 ArrayBuffer 对象,是处理二进制数据的核心类型currentChunk++if (currentChunk <= chunks) {buffers.push(chunk)loadNext() //读取下一个分片} else {resovle(buffers)}}//错误处理fileReader.onerror = function () {console.warn('oops, something went wrong.')}function loadNext() {let start = currentChunk * chunkSize,end = start + chunkSize >= file.size ? file.size : start + chunkSizelet chunk = blobSlice.call(file, start, end) //文件切片fileReader.readAsArrayBuffer(chunk) //触发一次异步读取,执行一次onload事件}//注意函数从这里开始执行!!!loadNext()})
}

在 JavaScript 中,Buffer 是处理二进制数据的核心对象,但浏览器环境和 Node.js 环境有所不同,

(浏览器环境)ArrayBuffer

  • 固定长度的原始二进制数据缓冲区

  • 不能直接操作,需要通过视图对象访问

  • 特点:

  • 1、智能引用:ArrayBuffer 只是指向原始文件的内存映射

  • 2、零拷贝技术:浏览器底层优化,不复制实际数据

  • 3、分片释放:上传后立即解除引用 → 垃圾回收

(Nodejs环境)Buffer 类

  • Node.js 特有的二进制处理类

注意:

1、fileReader.readAsArrayBuffer读取为二进制,内容为ArrayBuffer

2、 fileReader.readAsArrayBuffer 触发一次异步读取,会执行一次onload事件

尝试运行上述代码:

<template><div>我是home</div><input type="file" id="fileInput" @change="handleFileSelect"><button @click="handleUpload">上传</button>
</template><script lang="ts" setup>
import {ref} from 'vue'
//省略import上述方法
const fileBuffer = ref([])//buffer数组
let fileLength = ref(1) //原始分片数
const selectedFile = ref(null)//上传文件const handleFileSelect = (event) => {selectedFile.value = event.target.files[0]
}async function handleUpload(){// 文件分片fileBuffer.value = await uploadFile(selectedFile.value, 1 * 1024 * 1024)fileLength.value = fileBuffer.value.length}
</script>

发现一个问题:上传1.79M的一个apk文件,把chunkSize改成1*1024*1024(即1M),在onload里   console.log('chunk',chunk),发现 onload 运行了3遍

这是因为:

chunks为2,(因为一共1.79M,chunkSize为1M)

  1. 第一次 onload 后

    • currentChunk 从 0 → 1

    • 检查:1 <= 2 (true) → 调用 loadNext()

  2. 第二次 onload 后

    • currentChunk 从 1 → 2

    • 检查:2 <= 2 (true) → 调用 loadNext()

  3. 第三次调用 loadNext()

FileReader.readAsArrayBuffer()读到一个空的分片,又触发onload,因此打印看到了第三次执行

最后的打印结果:fileBuffer.value

AI说的修复逻辑,没试过~

fileReader.onload = function (e) {// 1. 获取当前分片数据(对应currentChunk索引)const chunk = e.target.resultbuffers.push(chunk)// 2. 递增为下一个分片做准备currentChunk++// 3. 检查是否还有更多数据(关键修复)const nextStart = currentChunk * chunkSizeif (nextStart < file.size) {// 还有数据 → 读取下一个分片loadNext()} else {// 所有分片完成resolve(buffers)}
}


http://www.hkcw.cn/article/JkihVEhBJD.shtml

相关文章

病理切片TLS比例作为免疫治疗响应和预后的预测因子

定义 三级淋巴结构 &#xff08;TLS&#xff0c;Tumor Lymphoid Structure&#xff09;&#xff1a;是指在非淋巴组织中的慢性炎症部位&#xff08;包括癌症&#xff09;形成的异位淋巴细胞聚集体。 目前&#xff0c;分割和量化 TLS 的金标准是基于对 T&#xff08;CD3: 用于…

Linux浅谈

Linux浅谈 一、什么是 Linux&#xff1f;先抛开 “内核”&#xff0c;看整体 可以把 Linux 系统 想象成一台 “组装电脑”&#xff1a; 最核心的零件是 “主板”—— 这就是 Linux 内核&#xff08;Kernel&#xff09;&#xff0c;负责管理电脑里的所有硬件&#xff08;比如 …

【模板-指南】

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

ICASSP2025丨融合语音停顿信息与语言模型的阿尔兹海默病检测

阿尔兹海默病&#xff08;Alzheimers Disease, AD&#xff09;是一种以认知能力下降和记忆丧失为特征的渐进性神经退行性疾病&#xff0c;及早发现对于其干预和治疗至关重要。近期&#xff0c;清华大学语音与音频技术实验室&#xff08;SATLab&#xff09;提出了一种将停顿信息…

吴艳妮获亚锦赛季军 妈妈:希望她恢复最佳状态 带伤参赛展现坚韧

因当地暴雨天气,原本计划于5月29日下午5时进行的亚洲田径锦标赛女子100米栏决赛延迟至当晚9时开赛。中国选手吴艳妮以13秒068的成绩获得季军。5月28日上午,吴艳妮以13秒07的成绩晋级决赛。赛后,她的母亲熊艳表示,比赛结果并不重要,只希望她尽快恢复,以最佳状态迎接未来的…

AMBA-AHB仲裁机制

前文 仲裁机制保证了任意时刻只有一个 master 可以接入总线。Arbiter 决定了哪个向其发出接入请求的 master 可以接入总线&#xff0c;这通过优先级算法实现。AHB规范并没有给出优先级算法&#xff0c;需要设计者根据具体的系统要求定义。一般情况下 arbiter 不会中断一…

长期口臭可能是你的身体在求救 三步教你自救

有些人表面光鲜亮丽一张嘴却让人“退避三舍”尤其在晨起、空腹时口臭问题更明显不仅尴尬还可能暗藏健康隐患科学应对口臭还你清新口气!先对号入座你的口臭是临时客串还是疾病信号?1、生理性口臭:临时“小插曲”饮食作祟:大蒜、洋葱、韭菜等含硫化合物的食物,会通过血液循环…

辰亦儒老婆曾之乔回应二胎计划 随缘就好

5月29日,女演员曾之乔出席活动时分享了她的产后生活,表示生完宝宝后感到非常幸福,并透露怀孕期间给儿子取的小名叫“甜蜜”。她还提到与丈夫辰亦儒采取“责任制”方式照顾宝宝,两人会排班负责。对于是否计划要二胎,她表示一切随缘。曾之乔和辰亦儒在2009年合作《爱似百汇》…

kafka学习笔记(三、消费者Consumer使用教程——从指定位置消费)

1.简介 Kafka的poll()方法消费无法精准的掌握其消费的起始位置&#xff0c;auto.offset.reset参数也只能在比较粗粒度的指定消费方式。更细粒度的消费方式kafka提供了seek()方法可以指定位移消费允许消费者从特定位置&#xff08;如固定偏移量、时间戳或分区首尾&#xff09;开…

旅客私自携带230万美元现金入境 折合人民币超1600万元

近日,皇岗海关在福田口岸旅检渠道查获一名旅客违规携带未申报的230万美元现金入境,折合人民币超过1600万元。皇岗海关关员在福田口岸旅检进境大厅对旅客及行李物品进行监管时,发现一名经“无申报通道”通关的旅客携带的行李机检图像异常。随后,该旅客被引导至查验区进一步检…

精度更高、速度更快!从RT-DETR到RF-DETR全面突破实时检测瓶颈

【导读】 YOLO虽快&#xff0c;但其依赖的非最大抑制&#xff08;NMS&#xff09;后处理拖累速度与精度。DETR架构首次实现无需NMS的“一对一”预测&#xff0c;却受限于计算成本。如今&#xff0c;RT-DETR 通过混合编码器、不确定性查询选择等创新突破实时瓶颈&#xff1b;RF…

提升搜索效率:深入了解Amazon Kendra的强大功能

从智能文档搜索到精准的自然语言处理&#xff0c;Amazon Kendra为企业提供了一个强大的解决方案&#xff0c;帮助我们突破传统搜索引擎的局限&#xff0c;快速实现信息的高效整合与检索&#xff0c;接下来让我们一起探索Amazon Kendra如何成为工作中的得力助手&#xff0c;提升…

社群营销:信任比流量值钱

你肯定见过那种群里天天甩链接的&#xff0c;动不动就所有人&#xff0c;点进去全是促销信息——这种玩意儿不叫社群营销&#xff0c;顶多是广告轰炸。 搞社群得先把自己当人&#xff0c;也把别人当人。别整那些机器人自动回复&#xff0c;谁半夜两点发消息都秒回&#xff0c;…

嵌入式工作项目中的线程管理(监控线程和重启线程的具体实现)

嵌入式工作项目中的线程管理(监控线程和重启线程的具体实现) 1. 背景 环境:ARMv7,Linux; 软件所处位置:应用层; 问题出现概率:偶先,概率极小; 问题描述: 一个负责校时的进程,里面有一个是网络校时的线程和一个 GPS 校时的线程,还有处理其他一些业务的线程;出现…

【图像处理基石】立体匹配的经典算法有哪些?

1. 立体匹配的经典算法有哪些&#xff1f; 立体匹配是计算机视觉中从双目图像中获取深度信息的关键技术&#xff0c;其经典算法按技术路线可分为以下几类&#xff0c;每类包含若干代表性方法&#xff1a; 1.1 基于区域的匹配算法&#xff08;Local Methods&#xff09; 通过…

Unity QFramework 简介

目录 什么是MVC模式&#xff1f; QFramework 架构提供了 Model 的概念 QFramework 架构引入 Command 的方式 QFramework 架构引入 Event事件机制 四个层&#xff1a;表现层、系统层、数据层、工具层 委托和回调函数的关系 命令和事件的区别 工具篇 QFramework整体基于M…

非线性声学计算与强化学习融合框架:突破复杂环境人机交互的新技术

随着人工智能的快速发展&#xff0c;尤其是在深度学习和强化学习领域&#xff0c;声学计算和人机交互进入前所未有的扩展和创新阶段。尽管传统声学方法取得了显著成功&#xff0c;但这些线性或准线性方法在实际环境中往往存在关键的不足&#xff0c;尤其在动态、复杂或混响环境…

广东河源再发3.0级地震 近期无大震风险

广东河源再发3.0级地震 近期无大震风险!中国地震台网正式测定,5月30日2时21分在广东河源市源城区(北纬23.72度,东经114.68度)发生3.0级地震,震源深度10千米。河源市地震局表示,目前未收到人员伤亡和财产损失报告。该局会商研判认为,本次地震是前一天5月29日13时17分发生…

极致视频压缩日记 - 1.2GB=>200MB - 低码率高画质 - 批量多目录自动转换脚本

效果图 格式av10.3M的码率&#xff0c;跟格式h.2645M的码率&#xff0c;画质竟然差不多&#xff01; GPU拉满全速编码&#xff01; 目标 1.视频瘦身储存&#xff0c;画质不变 2.自动批量压缩视频&#xff0c;多层目录递归处理 (脚本https://www.amjun.com/2327.html) 3.免费 (…

媒体:升学不再只有“独木桥” 职教贯通培养拓宽道路

媒体:升学不再只有“独木桥” 职教贯通培养拓宽道路!随着职教贯通培养模式的不断推进,我国学生的升学选择已经更加多元。高考不再是唯一的出路。5月28日,教育部公布2025年全国高考报名人数为1335万人,比2024年的1342万人减少7万人。这是自2017年以来高考报名人数首次减少。…