大文件如何快速上传

article/2025/9/30 2:06:17

之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需求,都能得到满足。小小开心了一把。

  但无论插件再怎么灵活,也难以应付所有的需求,比如,你要上传一个2G的文件。以现在我们的网速,恐怕再快也得传半小时。要命的是,如果你在上传到90%的时候不小心关掉了浏览器,或者是手一抖摁了F5,完了,一切还得从头再来。这种用户体验简直太糟糕了。所以,断点续传就十分有必要了。什么是续传我就不解释了,用QQ传文件这么多年,大家都见过了。

  这里要说的是断点续传都有哪些技术要点。使用传统的表单提交文件或是HTML5的FormData都是将文件“整块”提交,服务端取到该文件后再进行转移、重命名等操作,因此,无法实时保存文件的已上传部分。而且在http协议下,我们无法保持浏览器与服务端的长连接,不能以文件流的形式来提交。所以要解决的问题具体来讲有以下几点:

对上传的文件进行分割,每次只上传一小片。服务端接收到文件后追加到原来部分,最后合并成完整的文件。

每次上传文件片前先获取已上传的文件大小,确定本次应切割的位置

每次上传完成后更新已上传文件大小的记录

标识客户端和服务端的文件,保证不会把A文件的内容追加到B文件上

  在参考了张鑫旭大哥的这篇文章后,我将学到的技术应用在了我的插件Huploadify中,成功的添加了断点续传功能。在此将技术和插件都分享给大家。

工作原理/技术要点

  首先的首先,要明确,如果我们有一个10M的文件,每次切割上传1M,那么是需要发10次请求来完成的。在http协议下,只能这么搞。断点上传分三步来完成:

选择一个文件后,获取该文件在服务器上的大小,通过本地存储或自定义的函数来获取。

根据已上传大小切割文件,发出n次请求不断向服务器提交文件片,服务端不断追加文件内容

当已上传文件大小达到文件总大小时,上传结束 

  首先是文件的分割,HTML5新增了Blob数据类型,并且提供了一个可以分割数据的方法:slice(),其用法和字符串、数组的slice()方法一样,可以截取一个二进制文件的一部分。

  其次是文件片的保存与追加,我后台用PHP写的,先用file_get_contents获取文件的二进制格式,再用file_put_contents每次将文件追加,具体的写法可以参照后面,或者是下载我打包好的文件。

  接下来我们还需要实时保存已上传文件的大小,以便于下次上传前进行正确切割。使用HTML5的localStorage是一种方法,将已上传的大小保存在本地,下次上传前先从本地读取。不过这种方式是很局限的,抛开用户可能通过各种管家清除掉本地数据不讲,假如用户在A页面上传了一个文件的50%,然后在B页面想把该文件上传到另外一个地方,结果从本地一读文件已上传50%了,直接从51%的位置开始上传了,显然是个错误。问题就在于本地不能存太多的信息,通过File API只能获取到文件的原始名称,无法正确的与服务器上的文件正确匹配。所以真正在项目中用,还得依靠服务端来保存这些数据。

  关于如何将数据存在服务端,已经前端如何取数据,我在下面会讲到。

  技术要点就上面的那么多了,其实也没有多少技术含量哈~来看看我的插件如何使用吧。

续传功能的使用方法

  文件的引入就不讲了,可参考上一篇关于插件的介绍。关键点是新增的几个配置,先来看一下:

在服务端保存数据

  用户在使用上传的时候可能有各种你意想不到的操作,这里我发挥想象描述一下用户可能的行为:

同一台机器使用不同帐号登录,上传同一个文件

文件上传了一部分,然后修改了文件内容,再次上传

文件上传完成100%,再次上传该文件

同一个页面有多个上传按钮,上传同一个文件,或在不同页面上传同一个文件

  仅仅上面四条,是不是情况就够复杂了?再加上你系统还有自己的业务逻辑,所以在服务端保存已上传文件数据是非常有必要的。而且保存数据和获取数据的函数都交给你来定义,抱着插件有足够的灵活性。

  因为涉及到了服务端的技术,无法演示,我将我项目中的真实使用场景在此讲解一下,来展示一下如何自已定义方法来实现服务端保存数据的可靠上传。我定义的getUploadedSize函数如下:

文件初始化

文件上传完毕的代码

文件块的处理代码,up6对文件块的处理,以及文件续传的逻辑进行了大幅度的优化,开发者不需要关心续传的细节,因为up6默认就是自动续传

  我向后台的某个地址发送一个请求,传递文件名和文件的最后修改时间为参数,后台根据这两个参数来找到与前台所选择的文件对应的服务器上的文件,将服务器返回的文件大小return出去,来被插件使用。为什么要传递这两个参数呢?我们在前台无法知道服务器上的这个文件的名称,所以使用原始文件名作为一个辅助标识。为了防止用户在两次上传间隔修改了文件,我们把文件的最后修改时间也传给服务端,让服务端进行比较,若时间不对应则返回已上传大小为0,重新上传此文件。

  再来看后台都要做哪些工作。数据库中需要有一张表来记录每个已文件的情况,包含的字段大致有:

字段

描述

uid

用户ID

id

文件ID标识(唯一)

lenSvr

服务器文件大小

lenLoc

本地文件大小

blockOffset

文件块偏移(在整个文件中的位置)

blockSize

文件块大小

blockIndex

文件块索引(基于1)

blockMd5

文件块MD5

complete

当前文件是否已经传完

  根据client_filename和last_modified_date,再加上系统中的其他关联信息,可以定位到本次上传的文件在服务端的大小,然后返回给客户端。当然这是我自己的用法,你也可以根据自己的需求灵活设计。总之最终的目的就是要找到前台选择的文件在服务器上真正对应的文件,并将已上传大小正确返回。

  另外需注意的一点,就是在续传的第二步,不断提交文件片的过程中,也需要服务端准确定位到相应的文件,不能把A的数据追加到B上。采用的方式也是提交fileName和lastModifyDate两个参数(已写在插件内部,可服务端直接获取),服务端找到对应的文件进行追加。

  另外再啰嗦一句,后台获取文件的时候需要取成二进制的,而我们提交是使用FormData来提交的,所以PHP代码需要这么写:

file_put_contents('uploads/'.$filename,file_get_contents($_FILES["file"]["tmp_name"]),FILE_APPEND);

  如果上面的说明还是不够清楚,就需要你自己来探索一下了,毕竟考虑到插件可能应用在复杂的系统中,很多工作还是需要你来做的。或者你也可以给我留言,我很乐意为你解答疑惑。

该版本的其他改动

  从1.0到2.0,Huploadify又新加了很多东西,不过只是新加,使用方式跟之前的没有变化。例如上面的断点续传功能,你如果不想使用,只需设置breakPoints为false即可,插件仍按照以前的方式工作。除了断点续传这个大头,插件还做了如下改动:

增加了onSelect回调函数,在选择了文件之后触发,用法与uploadify官网的一致

up6提供了3个事件,选择文件,选择文件夹,粘贴

用户选择文件时会触发open_files,选择文件夹触发open_folders,粘贴会触发以上两个事件,因为用户可能粘贴的文件和文件夹

删除掉正在上传的文件,中断发送请求

完善了input file组件的accept属性支持,浏览时只显示运行的文件格式

  4. 对外开放了方法调用接口,upload、stop、cancel、disable、ennable。我在demo中有演示。使用方法如下:var up = $('#upload').Huploadify({

    auto:false,

    fileTypeExts:'*.jpg;*.png;*.exe;*.mp3;*.mp4;*.zip;*.doc;*.docx;*.ppt;*.pptx;*.xls;*.xlsx;*.pdf',

    multi:true

});

up.upload(1);//开始上传文件,接收一个参数,表示上传第几个文件,可传入*上传队列中的所有文件

up.stop();//暂停上传队列中的所有文件,不接收参数。用于开启了断点需传

up.cancel(1);//删除队列中的某个文件,接收一个参数,表示删除第几个文件,可传入*删除队列中的所有文件

up.disable();//使选择文件按钮失效,不接收参数

up.ennable();//使选择文件按钮生效,不接收参数  5. 修改其他已知bug

结束

  插件刚刚完成,与我们的后端程序员调试完成了断点续传功能暂未发现问题,欢迎大家在使用的时候给我提任何问题。老实来讲这个功能使用起来还是挺费解的,为了最大程度的保证灵活做成这样,大家可以与我多多交流~

  我在demo中使用了本地存储来做已上传文件大小的保存,下载压缩包后可看一下效果。上传一个比较大的视频文件,上传到中间关闭浏览器,再次打开浏览器上传同一个文件,会看到从上次断掉的地方继续上传。

详细内容可以参考我写的这篇文章:大文件上传解决方案


http://chatgpt.dhexx.cn/article/ccJ5Fcx5.shtml

相关文章

如何在GitHub上传大文件(≥100M)

学习工作中,有时会遇到需要将一些资源上传到GitHub的仓库(repository)上去,比如一些训练完的模型。但GitHub对于直接上传的文件有大小限制,超过100M的文件需要使用Git LFS才能上传。以下是我根据各位大神和自己的实操经…

大文件上传+解决方案

一、 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传; 支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传。刷新页面后继续传输。关闭浏览器后保留进度信息。 支持文件…

前端上传大文件的解决方案

最近遇见一个需要上传超大大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现。 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表格数据、上传影音文件等…

JAVA上传大文件的三种解决方案

我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。 首先我们需要了解的是上传文件三要素: 1.表单提交方式:post (get方式提交有大小限制,post没有) 2.表单的enct…

大文件如何快速上传?

前言 大文件快速上传的方案,相信你也有过了解,其实无非就是将 文件变小,也就是通过 压缩文件资源或者 文件资源分块 后再上传。 本文只介绍资源分块上传的方式,并且会通过 前端(vue3 vite) 和 服务端&…

Java如何上传大文件

1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出、还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工、挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通过浏览器上传至服务器&#xf…

Github上传大文件(>25MB)教程

Github上传大文件(>25MB)教程 Github上传大文件(>25MB)教程安装git安装Git Large File Storage实例踩坑点1:failed to push some refs to踩坑点2:main与master踩坑点3:Failed to connect …

如何高效的上传大文件?

业务场景:在很多业务中会涉及到文件上传,对于上传的文件大小要求也相对比较广,对于小文件而言我们使用MultipartFile上传就能解决,对于大文件来说可能也就将文件拆分成多份,一份一份的上传,大部分业务是足以…

请问:怎么实现大文件快速上传?

关注公众号 前端开发博客,领27本电子书 回复加群,自助秒进前端群 前言 大文件快速上传的方案,相信你也有过了解,其实无非就是将 文件变小,也就是通过 压缩文件资源 或者 文件资源分块 后再上传。 本文只介绍资源分块上…

超大文件上传解决方案

一、 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传; 支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传。刷新页面后继续传输。关闭浏览器后保留进度信息。 支持文件…

上传大文件(10G)的解决方案

需求: 项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在20G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以20G来进行限制。 PC端全平台支持,要求支持Windows,Mac,Linu…

linux操作系统实用教程课后答案,Linux操作系统案例教程课后习题答案

Linux操作系统案例教程课后习题答案 (3页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 11.90 积分 Linux操作系统案例教程课后习题答案第一章一 1.(D) 2.(B,C) 3.(A,B,D)4.(A,C,D ) …

第一章 Linux操作系统概述

接下来我将根据《Linux C编程完全解密》这本书,整理Linux系列相关笔记,并写成文章。本文将是该系列文章的第一篇。 第1章 Linux操作系统概述 1.1 认识Linux操作系统 1.1.1 Linux操作系统发展背景 Linux操作系统核心最早是由芬兰的Linus Torvalds于199…

SRE运维工程师笔记-安装linux系统(国产统信UOS操作系统)

SRE运维工程师笔记-安装linux系统(国产统信UOS操作系统) 1. 安装统信UOS系统1.1 针对统信UOS操作系统创建虚拟机环境1.2 安装国产统信UOS操作系统 1. 安装统信UOS系统 1.1 针对统信UOS操作系统创建虚拟机环境 简单介绍一下国产统信系统的安装&#xff…

Linux操作系统——定制自己的 Linux 系统

文章目录 22 定制自己的 Linux 系统22.1 基本介绍22.2 基本原理22.3 制作 min linux 思路分析22.4 操作步骤 22 定制自己的 Linux 系统 22.1 基本介绍 通过裁剪现有 Linux 系统(CentOS7.6),创建属于自己的 min Linux 小系统,可以加深我们对 linux 的理…

linux系统下的基本操作

Linux 操作系统 1. Linux操作系统认知 1.1 操作系统(Operation System简称OS) 定义 操作系统是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控…

Linux 系统相关介绍

Linux 系统相关说明 Linux 内核版本 没有图形化页面 稳定版 : 面向普通用户 开发版 : 面向开发人员 Linux 发行版 在内核版本的基础上, 增加比如桌面/音乐播放器等应用软件的系统 (不同公司的发行版, 名称不同)

讲讲Linux系统工程师的职业规划

时至今日,Linux操作系统越来越成为主流的桌面操作系统,自从在一年前看到了编程大神王垠写的一篇文章——完全用Linux工作,我决定学习使用Linux操作系统。因Windows在服务器领域的份额越来越低,学习具有安全和高效等特点的Linux操作…

Linux系统编程之进程退出,父进程等待子进程退出

1.首先讲一下进程的退出 进程的退出分为正常退出和异常退出: 正常退出: (1)main函数调用return (2)进程调用exit(),标准C库 (3)进程调用_exit()或_Exit(),属于系统调用 (4)进程最后一…