最近遇见一个需要上传超大大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现。

在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表格数据、上传影音文件等。如果文件体积比较大,或者网络条件不好时,上传的时间会比较长(要传输更多的报文,丢包重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成。

下面从文件上传方式入手,整理大文件上传的思路,并给出了相关实例代码,由于PHP内置了比较方便的文件拆分和拼接方法,因此服务端代码使用PHP进行示例编写。

本文相关示例代码位于github上,主要参考

聊聊大文件上传

大文件切割上传

文件上传的几种方式

首先我们来看看文件上传的几种方式。

普通表单上传

使用PHP来展示常规的表单上传是一个不错的选择。首先构建文件上传的表单,并指定表单的提交内容类型为enctype="multipart/form-data",表明表单需要上传二进制数据。

然后编写index.php上传文件接收代码,使用move_uploaded_file方法即可(php大法好…)

form表单上传大文件时,很容易遇见服务器超时的问题。通过xhr,前端也可以进行异步上传文件的操作,一般由两个思路。

文件编码上传

第一个思路是将文件进行编码,然后在服务端进行解码,之前写过一篇在前端实现图片压缩上传的博客,其主要实现原理就是将图片转换成base64进行传递

varimgURL = URL.createObjectURL(file);

ctx.drawImage(imgURL, 0, 0);

// 获取图片的编码,然后将图片当做是一个很长的字符串进行传递

vardata= canvas.toDataURL( "image/jpeg", 0.5);

在服务端需要做的事情也比较简单,首先解码base64,然后保存图片即可

$imgData = $_REQUEST[ 'imgData'];

$base64 = explode( ',', $imgData)[ 1];

$img = base64_decode($base64);

$url = './test.jpg';

if(file_put_contents($url, $img)) {exit(json_encode( array(

url => $url

)));

}

base64编码的缺点在于其体积比原图片更大(因为Base64将三个字节转化成四个字节,因此编码后的文本,会比原文本大出三分之一左右),对于体积很大的文件来说,上传和解析的时间会明显增加。

更多关于base64的知识,可以参考Base64笔记。

除了进行base64编码,还可以在前端直接读取文件内容后以二进制格式上传

// 读取二进制文件

functionreadBinary(text){vardata = newArrayBuffer(text.length);

varui8a = newUint8Array(data, 0);

for( vari = 0; i ui8a[i] = (text.charCodeAt(i) & 0xff);

}

console.log(ui8a)

}

varreader = newFileReader;

reader. = function{readBinary( this.result) // 读取result或直接上传

}

// 把从input里读取的文件内容,放到fileReader的result字段里

reader.readAsBinaryString(file);

formData异步上传

FormData对象主要用来组装一组用 发送请求的键/值对,可以更加灵活地发送Ajax请求。可以使用FormData来模拟表单提交。

letfiles = e.target.files // 获取input的file对象

letformData = newFormData;

formData.append( 'file', file);

axios.post(url, formData);

服务端处理方式与直接form表单请求基本相同。

iframe无刷新页面

在低版本的浏览器(如IE)上,xhr是不支持直接上传formdata的,因此只能用form来上传文件,而form提交本身会进行页面跳转,这是因为form表单的target属性导致的,其取值有

_self,默认值,在相同的窗口中打开响应页面

_blank,在新窗口打开

_parent,在父窗口打开

_top,在最顶层的窗口打开

framename,在指定名字的iframe中打开

如果需要让用户体验异步上传文件的感觉,可以通过framename指定iframe来实现。把form的target属性设置为一个看不见的iframe,那么返回的数据就会被这个iframe接受,因此只有该iframe会被刷新,至于返回结果,也可以通过解析这个iframe内的文本来获取。

functionupload{varnow = + newDate

varid = 'frame'+ now

$( "body").append( `

大文件上传

现在来看看在上面提到的几种上传方式中实现大文件上传会遇见的超时问题,

表单上传和iframe无刷新页面上传,实际上都是通过form标签进行上传文件,这种方式将整个请求完全交给浏览器处理,当上传大文件时,可能会遇见请求超时的情形

通过fromData,其实际也是在xhr中封装一组请求参数,用来模拟表单请求,无法避免大文件上传超时的问题

编码上传,我们可以比较灵活地控制上传的内容

大文件上传最主要的问题就在于:在同一个请求中,要上传大量的数据,导致整个过程会比较漫长,且失败后需要重头开始上传。试想,如果我们将这个请求拆分成多个请求,每个请求的时间就会缩短,且如果某个请求失败,只需要重新发送这一次请求即可,无需从头开始,这样是否可以解决大文件上传的问题呢?

综合上面的问题,看来大文件上传需要实现下面几个需求

支持拆分上传请求(即切片)

支持断点续传

支持显示上传进度和暂停上传

接下来让我们依次实现这些功能,看起来最主要的功能应该就是切片了。

文件切片

参考:大文件切割上传

编码方式上传中,在前端我们只要先获取文件的二进制内容,然后对其内容进行拆分,最后将每个切片上传到服务端即可。

在Java中,文件FIle对象是Blob对象的子类,Blob对象包含一个重要的方法slice,通过这个方法,我们就可以对二进制文件进行拆分。

下面是一个拆分文件的示例,对于up6来说开发者不需要关心拆分的细节,由控件帮助实现,开发者只需要关心业务逻辑即可。

控件上传的时候会为每一个文件块数据添加相关的信息,开发者在服务端接收到数据后可以自已进行处理。

服务器接收到这些切片后,再将他们拼接起来就可以了,下面是PHP拼接切片的示例代码

对于up6来说,开发人员不需要进行拼接,up6已经提供了示例代码,已经实现了这个逻辑。

保证唯一性,控件会为每一个文件块添加信息,如块索引,块MD5,文件MD5

断点续传

up6自带续传功能,up6在服务端已经保存了文件的信息,在客户端也保存了文件的进度信息。在上传时控件会自动加载文件进度信息,开发者不需要关心这些细节。在文件块的处理逻辑中只需要根据文件块索引来识别即可。

此时上传时刷新页面或者关闭浏览器,再次上传相同文件时,之前已经上传成功的切片就不会再重新上传了。

服务端实现断点续传的逻辑基本相似,只要在getUploadSliceRecord内部调用服务端的查询接口获取已上传切片的记录即可,因此这里不再展开。

此外断点续传还需要考虑切片过期的情况:如果调用了mkfile接口,则磁盘上的切片内容就可以清除掉了,如果客户端一直不调用mkfile的接口,放任这些切片一直保存在磁盘显然是不可靠的,一般情况下,切片上传都有一段时间的有效期,超过该有效期,就会被清除掉。基于上述原因,断点续传也必须同步切片过期的实现逻辑。

续传效果

上传进度和暂停

通过xhr.upload中的progress方法可以实现监控每一个切片上传进度。

上传暂停的实现也比较简单,通过xhr.abort可以取消当前未完成上传切片的上传,实现上传暂停的效果,恢复上传就跟断点续传类似,先获取已上传的切片列表,然后重新发送未上传的切片。

由于篇幅关系,上传进度和暂停的功能这里就先不实现了。

实现效果:

小结

目前社区已经存在一些成熟的大文件上传解决方案,如七牛SDK,腾讯云SDK等,也许并不需要我们手动去实现一个简陋的大文件上传库,但是了解其原理还是十分有必要的。

本文首先整理了前端文件上传的几种方式,然后讨论了大文件上传的几种场景,以及大文件上传需要实现的几个功能

通过Blob对象的slice方法将文件拆分成切片

整理了服务端还原文件所需条件和参数,演示了PHP将切片还原成文件

通过保存已上传切片的记录来实现断点续传

还留下了一些问题,如:合并文件时避免内存溢出、切片失效策略、上传进度暂停等功能,并没有去深入或一一实现,继续学习吧。

—————END—————
更多精彩:Java实战项目视频,给需要的读者,收藏!Centos7搭建k8s环境教程,一次性成功!看看人家那后端API接口写得,那叫一个优雅!一款开源的视频弹幕功能项目,不用重复造轮子了!一款开源 SpringBoot 后端管理系统,代码开源了!开源 SpringBoot 商城系统,真香!
关注公众号,查看更多优质文章

最近,整理一份Java资料Java从0到1,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:关注公众号并回复Java领取,更多Java内容陆续奉上。明天见(。・ω・。)ノ♡

antd upload手动上传_SpringBoot 如何上传大文件?相关推荐

  1. 大文件分片上传前端框架_js实现大文件分片上传的方法

    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...

  2. 上传问题总结(文件大小检测,大文件上传)

    PHP上传问题总结(文件大小检测,大文件上传) 由于涉及到本地和服务器两方面的安全问题,所以基于input type="file"形式的页面文件上传一直处于一个很尴尬的位置.一方面 ...

  3. jquery PHP大文件上传,Jquery和BigFileUpload实现大文件上传及进度条显示

    实现方法:用到了高山来客 的bigfileupload组件,用高山来客的方法,弹出一个模式窗口,然后不停刷新获取进度,始终觉得体验感不好,于是想到用jquery来实现无刷新进度显示,因为提交页面后, ...

  4. java是怎么实现文件上传的_java怎么实现大文件上传

    Q1:javaWeb能和ftp实现大文件上传吗 java上传可以使用common-fileupload上传组件的.common-fileupload是jakarta项目组开发的一个功能很强大的上传文件 ...

  5. java文件上传控件_java实现大文件上传控件

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  6. antd Upload手动上传(react)

    情况介绍 在antd官方提供的upload组件案例中,都使用了action属性直接上传,唯一手动上传的一个例子(如下图)也不够好用,可能不能满足项目的需求,所以我们需要对其进行一些修改,并加入一些别的 ...

  7. antd upload手动上传_antd 手动上传文件

    先说我要实现的效果:我想用antd 的 upload 实现手动上传文件,上传文件时还有附加参数 我看了官网上说在beforeUpload中返回false,然后通过按钮点击事件触发上传. Q1:附加参数 ...

  8. antd upload手动上传_Flask上传文件

    Flask上传文件 上传文件包括很多,比如用户头像,文章图片,文件分享等等,它也涉及到很多内容:上传文件,过滤文件类型,限制大小,文件名的编辑,拖拽上传,进度条,文件命名,文件目录的管理等等. 文件上 ...

  9. antd upload手动上传_基于MVVCTP5的文件上传

    现如今在市面上常见的web开发理念一般是两种,一种是MVC格式的,比较传统,而项目较大的开发,一般由团队完成,而MVC格式就显得有些不够合理 .于是 ,在这种情况下诞生了另外一种开发理念,我们叫MVV ...

最新文章

  1. jquery实现心算练习
  2. 使iPhone手机持续振动
  3. halcon区域腐蚀膨胀算子_超越halcon速度的二值图像的腐蚀和膨胀,实现目前最快的半径相关类算法(附核心源码)。...
  4. 路由到另外一个页面_一个简单的Vue按钮级权限方案
  5. PyODPS开发中的最佳实践
  6. 厦门高桔科技有限公司
  7. ofo败局中唯一赚到钱的只有他?当事人回应......
  8. 小姐姐给我讲,一听就懂的财务报表
  9. C# 压缩PDF图片
  10. java课程 教 学小结_Java私塾中级课程学习感受和小结3
  11. python身份证号码解析编程_Python实现身份证号码解析
  12. Symbolic Math Toolbox——MuPAD
  13. 电子计算机off键是什么意思,off键是什么意思
  14. 2012人类将从“微博体”过渡到“微媒体”。至于你信不信,反正我信了
  15. jpg转bmp(使用libjpeg库)
  16. 手把手教你在VSCode中使用Git
  17. 洗礼灵魂,修炼python(56)--爬虫篇—知识补充—编码之url编码
  18. 浅析计算机信息管理系统任务书,计算机工程系学生就业信息管理系统任务书
  19. [资料] 为实现正确信号调理的噪声计算,这七个步骤你得get(转载)
  20. 剑指offer 24. 反转链表

热门文章

  1. apache commons - lang 常用方法记录
  2. Xcode:PhoneGap 2.5.0项目创建方法
  3. IT人终于把自己熬成了民工
  4. 46muduo库使用示例(五)
  5. 15muduo_base库源码分析(六)
  6. 【论文写作】SpringMVC学籍管理系统如何画用例图
  7. 【免费毕设】基于PHP实现的WEB图片共享系统(源代码+论文)
  8. tl wdr5660虚拟服务器,TP-Link TL-WDR5660路由器怎么设置?
  9. 热血动漫番太好看了!用Python爬取了1T的动漫,内存都爆了
  10. mysql 当前用户连接数,查看mysql当前连接数的方法详解