锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

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

时间:2023-04-08 06:07:00 120a单相固态继电器mgr

最近,我遇到了需要上传大型文件的需求,并研究了七牛和腾讯云的切片分段上传功能。因此,我整理了前端大型文件上传相关功能的实现。

在某些业务中,大文件上传是一个更重要的交互场景,如上传到仓库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知识4知识Base64笔记。

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

//读取二进制文件

functionreadBinary(text){

vardata = newArrayBuffer(text.length);

varui8a = newUint8Array(data, 0);

for( vari = 0; i < text.length; 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( `