在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的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,然后保存图片即可
i m g D a t a = imgData = imgData = _REQUEST[ ‘imgData’];
b a s e 64 = e x p l o d e ( ′ , ′ , base64 = explode( ',', base64 = explode( ′,′, imgData)[ 1];
i m g = b a s e 6 4 d e c o d e ( img = base64_decode( img = base64decode(base64);
$url = ‘./test.jpg’;
if(file_put_contents( u r l , url, 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 < 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
( " b o d y " ) . a p p e n d ( ‘ < i f r a m e s t y l e = " d i s p l a y : n o n e ; " n a m e = " ( "body").append( `<iframe style="display:none;" name=" ( "body").append( ‘<iframe style="display:none;" name="{id}" id=“${id}” />`);
var f o r m = form = form = ( “#myForm”)
$form.attr({
“action”: ‘/index.php’,
“method”: “post”,
“enctype”: “multipart/form-data”,
“encoding”: “multipart/form-data”,
“target”: id
}).submit
$( “#”+id).on( “load”, function{
varcontent = $( this).contents.find( “body”).text
try{
vardata = JSON.parse(content)
} catch(e){
console.log(e)
}
})
}
大文件上传
现在来看看在上面提到的几种上传方式中实现大文件上传会遇见的超时问题,
表单上传和iframe无刷新页面上传,实际上都是通过form标签进行上传文件,这种方式将整个请求完全交给浏览器处理,当上传大文件时,可能会遇见请求超时的情形
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
言尽于此,完结
无论是一个初级的 coder,高级的程序员,还是顶级的系统架构师,应该都有深刻的领会到设计模式的重要性。
- 第一,设计模式能让专业人之间交流方便,如下:
程序员A:这里我用了XXX设计模式
程序员B:那我大致了解你程序的设计思路了
- 第二,易维护
项目经理:今天客户有这样一个需求…
程序员:明白了,这里我使用了XXX设计模式,所以改起来很快
- 第三,设计模式是编程经验的总结
程序员A:B,你怎么想到要这样去构建你的代码
程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题
- 第四,学习设计模式并不是必须的
程序员A:B,你这段代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
搜集费时费力,能看到此处的都是真爱!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
代码使用的是XXX设计模式对吗?
程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的
[外链图片转存中…(img-EDj4YB1I-1713386876730)]
从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!
[外链图片转存中…(img-cvOdzNeu-1713386876731)]
搜集费时费力,能看到此处的都是真爱!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!