Web的几种上传方式总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Web的⼏种上传⽅式总结
问题
⽂件上传在WEB开发中应⽤很⼴泛。
⽂件上传是指将本地图⽚、视频、⾳频等⽂件上传到服务器上,可以供其他⽤户浏览或下载的过程。
以下总结了常见的⽂件(图⽚)上传的⽅式和要点处理。
表单上传
这是传统的form表单上传,使⽤form表单的input[type=”file”]控件,可以打开系统的⽂件选择对话框,从⽽达到选择⽂件并上传的⽬的,它的好处是多浏览器兼容,它是web开发者最常⽤的⼀种⽂件上传⽅式。
表单的代码如下:
<form method="post" action="http://uploadUrl" enctype="multipart/form-data">
<input name="file" type="file" accept="image/gif,image.jpg"/>
<input name="token" type="hidden"/>
<input type="submit" value="提交"/>
</form>
以下是表单上传⼏个关键点:
method="post":采⽤post⽅式提交数据
enctype="multipart/form- data":采⽤multipart格式上传⽂件,此时request头会显⽰ Content-Type:multipart/form-data; boundary=—-WebKitFormBoundaryzr34cwJ67R95KQC9
action:标明上传的服务端处理地址
type="file":使⽤input的file控件上传
如果是多⽂件批量上传,可以将input[type=”file”]的name属性设置为如:name=”file[]”
accept属性是HTML5的新属性,它规定了可通过⽂件
上传提交的⽂件类型
上传的触发事件可以是:input[type=”file”]的onChange触发,也可以由⼀个独⽴的按钮的onClick使整个表单提交,此时还可以
⽤input[type="hidden"]带⼀些其它的参数,⽐如Token来源验证等等。
Ajax⽆刷新上传
Ajax⽆刷新上传的⽅式,本质上与表单上传⽆异,只是把表单⾥的内容提出来采⽤ajax提交,并且由前端决定请求结果回传后的展⽰结果,不⽤像直接表单上传那样刷新和跳转页⾯。
在这⾥,我们采⽤jQuery来作为操作DOM和创建ajax提交的js基础库。
html代码⽚段如下:
<form>
<input id="file" name="file" type="file" />
<input id="token" name="token" type="hidden" />
</form>
javascript代码⽚段如下:
$("#file").on("change", function(){
var formData = new FormData();
formData.append("file", $("#file")[0].files);
formData.append("token", $("#token").val());
$.ajax({
url: "http://uploadUrl",
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function(response){
// 根据返回结果指定界⾯操作
}
});
});
我们使⽤了file控件的change来触发上传事件,当然你也可以使⽤某个按钮来触发表单提交。
提交数据时,⽤到了FormData对象来发送⼆进制⽂件,FormData构造函数提供的append()⽅法,除了直接添加⼆进制⽂件还可以附带⼀些其它的参数,作为XMLHttpRequest实例的参数提交给服务端。
使⽤jQuery提供的ajax⽅法来发送⼆进制⽂件,还需要附加两个参数:
processData: false // 不要对data参数进⾏序列化处理,默认为true
contentType: false // 不要设置Content-Type请求头,因为⽂件数据是以 multipart/form-data 来编码
Flash上传
很多时候上传的需求要求显⽰上传进度、中断上传过程、⼤⽂件分⽚上传等等,这时传统的表单上传很难实现这些功能,于是产⽣了使⽤Flash上传的⽅式,它采⽤Flash作为⼀个中间代理层,代替客户端跟服务端通信,此外,它也对客户端的⽂件选择⽅⾯拥有更多的控制权,⽐input[type=”file”] 要⼤得多。
在这⾥我使⽤了jQuery封装好的uploadify插件来进⾏演⽰,⼀般这类插件都⾃带了上传⽤的Flash⽂件,因为跟服务端回传的数据和展⽰跟客户端的交互,都是Flash⽂件的接⼝跟插件来对接的。
<div id="file_upload"></div>
html部分很简单,预留⼀个hook后,插件会在这个节点内部创建Flash的object,并且还附带创建了上传进度、取消控件和多⽂件队列展⽰等界⾯。
$(function() {
$("#file_upload").uploadify({
auto: true,
method: "Post",
width: 120,
height: 30,
swf: './uploadify.swf',
uploader: 'http://uploadUrl',
formData: {
token: $("#token").val()
},
fileObjName: "file",
onUploadSuccess: function(file, data, response){
// 根据返回结果指定界⾯操作
}
});
});
截图粘贴上传
我们发现现在有好多上传应⽤已经提供了截图粘贴上传功能,如WebUploader,它就⽀持QQ截图然后粘贴上传。
⾸先,截图粘贴上传的核⼼思想是,监听粘贴事件,然后获取剪切板中的数据,如果是⼀张图⽚,则触发上传事件。
代码⽚段如下:
$("textarea").on("paste", function(e){
e.stopPropagation();
var self = this;
var clipboardData = e.originalEvent.clipboardData;
if (clipboardData.items.length <= 0) {
return;
}
var file = clipboardData.items[0].getAsFile();
if (!file) {
return;
}
var formData = new FormData();
formData.append("file", file);
formData.append("token", $("#token").val());
$.ajax({
url: "http://uploadUrl",
type: "POST",
data: formData,
}).done(function(response) {
// 根据返回结果指定界⾯操作
});
e.preventDefault();
});
从上⾯代码可以看出,上传的过程都是⼀样的,主要是获取⽂件的⽅式。
当进⾏粘贴(右键paste/ctrl+v)操作时,触发剪贴板事件’paste’,从系统剪切板获取内容,⽽系统剪切板的数据在不同浏览器保存在不同的位置:
IE内核:windows.clipboardData
其它:e.originalEvent.clipboardData
拖拽上传
拖拽上传的⽅式,⽀持的浏览器⽐较少,因为它⽤到了HTML5的两个新的属性(API)⼀个是Drag and Drop,⼀个是File API。
上传域监听拖拽的三个事件:dragEnter、dragOver和drop,分别对应拖拽⾄、拖拽时和释放三个操作的处理机制,当然你也可以监听dragLeave事件。
HTML5的File API提供了⼀个FileList的接⼝,它可以通过拖拽事件的e.dataTransfer.files来传递的⽂件信息,获取本地⽂件列表信息。
File API在HTML5规范中只是草案,在 W3C 草案中,File 对象只包含⽂件名、⽂件类型和⽂件⼤⼩等只读属性。
但部分浏览器在草案之外提供了⼀个名为 FileReader 的对象,⽤以读取⽂件内容,并且可以监控读取状态,它提供的⽅法有: “readAsBinaryString”
,”readAsDataURL” ,”readAsText” ,”abort” 等。
代码⽚段如下:
// dragenter
$("#textarea").on("dragenter", function(e){
e.preventDefault();
});
// dragover
$("#textarea").on("dragover", function(e){
e.preventDefault();
});
// drop
$("#textarea").on("drop", function(e){
e.stopPropagation();
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
_.each(files, function(file) {
if (!/^image*/.test(file.type)) {
return;
}
var fileReader = new FileReader();
fileReader.onload = function() {
//uploadFile(file);
};
fileReader.readAsDataURL(file);
});
});
拖拽上传过程中的⼏个关键点:
在drop事件触发后通过e.dataTransfer.files获取拖拽⽂件列表,在jQuery中是e.originalEvent.dataTransfer.files
拖拽上传仅⽀持图⽚,⽂件对象中file.type标识了⽂件类型。
由于可能是多图拖拽,所以可以遍历图⽚上传,这⾥⽤了Underscore的each⽅法。
这⾥⽤readAsDataURL读取⽂件内容为⼆进制⽂件,你还可以将其转换为Base64⽅式上传,只是http协议⾥⾯存在对⾮⼆进制数据的上传⼤⼩限制为2M。
上传的过程跟前⾯的⽅式相同,即:创建FormData对象并发起Ajax请求。
拍照上传
拍照上传可以是PC上的摄像头拍照上传也可以是⼿机等移动设备的拍照上传。
⼿机上的拍照上传最常见就是我们使⽤微信发照⽚了。
⼿机实现拍照上传的代码:
<input type=file accept="image/*">
<input type=file accept="video/*">
ios 有拍照、录像、选取本地图⽚功能,部分android只有选取本地图⽚功能。
上传与安全
上传⽂件时必须做好⽂件的安全性,除了前端必要的验证,如⽂件类型、后缀、⼤⼩等验证,重要的还是要在后台做安全策略。
这⾥我列举⼏个注意点:
后台需要进⾏⽂件类型、⼤⼩、来源等验证
定义⼀个.htaccess⽂件,只允许访问指定扩展名的⽂件。
将上传后的⽂件⽣成⼀个随机的⽂件名,并且加上此前⽣成的⽂件扩展名。
设置上传⽬录执⾏权限,避免不怀好意的⼈绕过如图⽚扩展名进⾏恶意攻击,拒绝脚本执⾏的可能性。