文件上传网站源码-原生JS上传大文件源码

最近遇到一个上传非常大文件的需求,考察了七牛和腾讯云的分段上传功能文件上传网站源码,所以这里就实现了后端大文件上传相关功能。

在个体业务中,上传大文件是一个比较重要的交互场景文件上传网站源码,比如上传比较大的Excel表格数据到库、上传音视频文件等等。 如果文件体积比较大,或者网络状况不好,上传时间会较长(需要传输的数据包较多,丢包重传的概率也较大),用户无法刷新页面,只能耐心等待请求完成。

我们先从文件上传方法开始,梳理一下上传大文件的思路,并给出相关示例代码。 由于PHP对外有方便的文件分割和拼接方式,因此服务器代码采用PHP进行示例编译。

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

谈谈大文件上传

剪切并上传大文件

文件上传的几种形式

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

正常形式上传

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

然后编译index.php上传文件接收代码,使用move_uploaded_file方法(php大法不错...)

当以表单上传大文件时,很容易遇到服务器超时的问题。 通过xhr,前端还可以异步上传文件。 一般来说,有两种想法。

文件编码上传

第一个想法是对文件进行编码,然后在服务器端对其进行解码。 之前写过一篇关于后端图片压缩和上传的博客。 主要实现原理是将图像转为base64进行传输。

varimgURL = URL.createObjectURL(文件);

ctx。 绘制图像(imgURL, 0, 0);

//获取图片的编码,然后将图片作为长字符串传递

vardata = canvas.toDataURL(“图像/jpeg”, 0.5);

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

$imgData = $_REQUEST['imgData'];

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

$img = base64_decode($base64);

$url = './test.jpg';

if(file_put_contents($url, $img)) {

退出(json_encode(数组(

网址 => $网址

)));

Base64编码的缺点是其体积比原图片要大(因为Base64将三个字节转换为四个字节,所以编码后的文本会比原文本大三分之一左右),对于体积大的文件来说,上传并且解析时间将显着减少。

关于base64的更多信息,请参考Base64注释。

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

// 读取二进制文件

函数readBinary(文本){

vardata = newArrayBuffer(text.length);

varui8a = newUint8Array(数据, 0);

for( vari = 0; i < 文本。长度; i++){

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

控制台.log(ui8a)

varreader = newFileReader;

读者。 =函数{

readBinary( this.result) //读取结果或直接上传

//将从input中读取到的文件内容放入fileReader的结果数组中

读者。 readAsBinaryString(文件);

formData异步上传

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

letfiles = e.target.files //获取输入文件对象

letformData = newFormData;

formData.append('文件', 文件);

轴。 发布(网址,表单数据);

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

iframe不刷新页面

在低版本浏览器(如IE)上,xhr不支持直接上传formdata,所以只能使用form上传文件,而表单提交本身会跳转到页面,这是表单的target属性导致的形式。 ,其值为

_self,默认,在同一窗口中打开响应页面

_blank,在新窗口中打开

_parent,在父窗口中打开

_top,在最上面的窗口中打开

framename,在iframe中打开指定名称

如果需要让用户体验异步上传文件的感觉,可以通过framename指定一个iframe。 将表单的target属性设置为不可见的iframe,那么返回的数据就会被iframe接受,所以只会刷新iframe,通过解析iframe中的文本也可以得到返回的结果。

函数上传{

varnow = +newDate

varid = '框架' + 现在

$(“正文”). 追加(``);

var $form = $("#myForm")

$form.attr({

"行动": '/index.php',

“方法”:“帖子”,

"enctype": "多部分/表单数据",

“编码”:“多部分/表单数据”,

“目标”:id

})。提交

$( "#"+id).on( "加载", 函数{

varcontent = $(this).contents.find("body").text

尝试 {

vardata = JSON. 解析(内容)

} 捕获(e){

安慰。 日志(e)

})

大文件上传

现在我们就来看看前面提到的上传表单中实现大文件上传时遇到的超时问题。

表单上传和iframe页面无刷新上传实际上是通过form标签上传文件。 在该方法中,整个请求完全交给浏览器处理。 当上传大文件时,请求可能会超时。

通过fromData,实际上是在xhr中封装了一组请求参数,用于模拟表单请求,并不能防止大文件上传超时的问题

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

上传大文件的主要问题是,在同一个请求中,需要上传大量数据,导致流程较长,并且上传失败后需要重新启动。 试想一下,如果我们把这个请求拆分成多个请求,每个请求的时间就会缩短,而且如果一个请求失败,我们只需要重新发送这个请求,而不用从头开始。 文件上传问题怎么办?

根据之前的问题,看来大文件的上传需要满足以下要求

支持拆分上传请求(即分块)

支持断点续传

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

接下来我们依次实现一下这个功能。 看来最重要的功能应该是切割了。

文件切割

参考:大文件切割上传

在编码方式上传中,我们只需要在后端获取文件的二进制内容,然后将内容进行分割,最后将每一块上传到服务器。

在Java中,文件FIle对象是Blob对象的泛型类型,而Blob对象包含一个重要的方法slice,通过它我们可以对二进制文件进行分割。

以下是分割文件的示例。 对于up6来说,开发者不需要关心分裂的细节。 通过控件来实现,开发者只需要关心业务逻辑。

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

服务器收到这种切割后,就可以将它们拼接在一起。 以下是PHP拼接和裁剪的示例代码

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

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

http

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

此时,上传时请刷新页面或关闭浏览器。 再次上传同一文件时,之前成功上传的切片将不会重新上传。

服务端续传上传的逻辑基本类似,只要在getUploadSliceRecord内部调用服务端的查询socket来获取上传切片的记录即可,这里不再展开。

另外,还需要考虑过期的chunk:如果调用mkfile接口,可以将c盘上的chunk的内容删除。 如果客户端从来不调用mkfile接口,那么chunk仍然保存在c盘,其实是不可靠的。 一般来说,切片上传是有有效期的。 过了有效期,它们将被删除。 基于以上原因,断点续传还必须同步区块过期的实现逻辑。

持续疗效

上传进度和暂停

通过xhr.upload中的progress方法,可以监控每个区块的上传进度。

上传暂停的实现也比较简单。 通过xhr.abort,可以取消当前未完成的上传块的上传,实现上传暂停的疗效。 恢复上传与恢复上传类似。 首先获取已上传的块列表,然后重新启动发送未上传的块。

由于篇幅限制,这里不会实现上传进度和暂停的功能。

达到疗效:

概括

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

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

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

整理了服务器端恢复文件所需的条件和参数,并演示了PHP如何将块恢复到文件

通过保存上传块的记录从断点恢复上传

还剩下一些问题,比如:合并文件时防止内存溢出、切片失效策略、上传进度暂停等功能,还没有深入或者一一实现,继续学习

大部分后端代码逻辑是相同的,目前只能支持MySQL、Oracle、SQL。 使用前需要配置数据库。 你可以参考我写的这篇文章:%E5%A4%A7%E6%96%87%E4%BB%B6%E6%96%AD%E7%82%B9%E7% BB%AD%E4%BC% A0%E4%B8%8A%E4%BC%A0/

欢迎加群讨论:374992201

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 网站源码 文件上传网站源码-原生JS上传大文件源码 https://www.wkzy.net/game/159959.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务