HTML5关于上传API的一些使用(上)
HTML5提供了很多有用的API,其中就包括上传的API,XMLHttpRequest2.0,在HTML5时代之前,需要进行二进制的上传一般都会才用flash的方案,但是当XMLHttpRequest2.0出来之后,完全可以使用HTML5的上传解决方案,能够非常方便的进行二进制上传进度的显示,上传图片的本地预览,甚至可以做到断点续传,分片上传,多文件上传等各种复杂的底层功能。
首先回顾一下XMLHttpRequest1.0的传输过程
关于XMLHttpRequest
初始化XMLHttpRequest
想要使用XMLHttpRequest进行传输文件,首先我们得创建一个XMLHttpRequest对象, 而每创建一个XMLHttpRequest的时候会产生readyState这个属性,当一个 XMLHttpRequest 初次创建时,这个属性的值从 0 开始,直到接收到完整的 HTTP 响应,这个值增加到 4。 5 个状态中每一个都有一个相关联的非正式的名称,下表列出了状态、名称和含义:
状态 | 名称 | 描述 |
0 | Uninitialized | 初始化状态。XMLHttpRequest 对象已创建或已被 abort() 方法重置。 |
1 | Open | open() 方法已调用,但是 send() 方法未调用。请求还没有被发送。 |
2 | Sent | Send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。 |
3 | Receiving | 所有响应头部都已经接收到。响应体开始接收但未完成。 |
4 | Loaded | HTTP 响应已经完全接收。 |
var xhr = new XMLHttpRequest(); //readyState为0
xhr.open方法设置初始参数
然后需要初始化一些HTTP请求的参数但是这里只是初始化,也就是说设置一些上传所需要的参数,但是并不会进行上传
xhr.open(method, url, async, username, password); //readyState为1
method 参数是用于请求的 HTTP 方法。值包括 GET、POST 和 HEAD。
url 参数是请求的主体。大多数浏览器实施了一个同源安全策略,并且要求这个 URL 与包含脚本的文本具有相同的主机名和端口。
async 参数指示请求使用应该异步地执行。如果这个参数是 false,请求是同步的,后续对 send() 的调用将阻塞,直到响应完全接收。如果这个参数是 true 或省略,请求是异步的,且通常需要一个 onreadystatechange 事件句柄。
username 和 password 参数是可选的,为 url 所需的授权提供认证资格。如果指定了,它们会覆盖 url 自己指定的任何资格。
xhr.send()方法发送请求
对HTTP的请求的参数设置完之后就可以进行发送了
xhr.send(); //readyState为2
xhr.send()会导致一个HTTP请求。如果之前没有调用 open()或者说 readyState 不是 1,xhr.send() 则会跑出一个错误。否则,它发送一个 HTTP 请求,该请求由以下几部分组成: 之前调用xhr.open() 时指定的 HTTP 方法、URL 以及认证资格(如果有的话)。 之前调用 xhr.setRequestHeader() 时指定的请求头部(如果有的话)。 传递给这个方法的 body 参数。
请求发布后,send() 把 readyState 设置为 2,并触发 onreadystatechange 事件。
关于 onreadystatechange 事件
onreadystatechange实际上是每当readyState发生改变的时候就会触发的参数,也就是说我们可以直接在onreadystatechange事件中去判断readyState的值,假如readyState等于4的时候就可以执行上传完成后的回调方法。
如果之前调用的xhr.open() 参数 async 为 false,这个方法会阻塞并不会返回,直到 readyState 为 4 并且服务器的响应被完全接收。否则,如果 async 参数为 true,或者这个参数省略了,xhr.send() 立即返回。如果服务器响应带有一个 HTTP 重定向,xhr.send() 方法或后台线程自动遵从重定向。当所有的 HTTP 响应头部已经接收,xhr.send() 或后台线程把 readyState 设置为 3 并触发 onreadystatechange 事件句柄。如果响应较长,xhr.send() 或后台线程可能在状态 3 中触发 onreadystatechange 事件句柄:这可以作为一个下载进度指示器。最后,当响应完成,xhr.send() 或后台线程把 readyState 设置为 4,并最后一次触发事件句柄。
通过上面的初始化,open,send,已经监控onreadystatechange事件的返回值用以触发回调方法,我们就完成了一个ajax请求。
关于XMLHttpRequest2.0
而关于HTML5中增加XMLHttpRequest2.0的新功能主要包括下面这些:
- 可以设置HTTP请求的时限。
- 可以使用FormData对象管理表单数据。
- 可以上传文件。
- 可以请求不同域名下的数据(跨域请求)。
- 可以获取服务器端的二进制数据。
- 可以获得数据传输的进度信息。
我们这里主要说和上传文件比较密切相关的部分
关于FormData
AJAX通常可以用来进行模拟表单的提交,也就是说XMLHttpRequest1.0中大家经常使用的无刷新提交数据,为了方便对于表单的处理,HTML新增了一个FormData对象,可以用来模拟表单。使用如下:
var formData=new FormData();
formData.append('name',"Jack");
formData.append('uid',666666);
上面的三行代码就实现了往一个FormData()对象里面插入了两个字段,一个name,一个uid 然后我们可以就像XMLHttpRequest1.0的时候一样进行ajax的提交即:
var xhr=new XMLHttpRequest();
xhr.open("post",url);
xhr.send(formData);
关于HTML5多文件的上传
那我们实际上想要用HTML5解决上传文件的过程应该怎么解决呢? HTML5中针对<input type="file"/>
标签新加了一个files的对象,并且通过对input标签设置multiple属性,则可以实现添加多个文件的功能,而files实际上是一个数组对象,里面存的则全是这个file标签中的文件;
那么我们想要上传文件就很简单了,直接循环files对象获取到用户添加到file控件中的文件并且都通过FormData对象的append方法添加到FormData中去,然后进行发送即可。
var formData=new FormData();
for(var i=0;i<files.length;i++){
formData.append(i,files[i]);
}
var xhr=new XMLHttpRequest();
xhr.open("post",url);
xhr.send(formData);
通过上面这些代码就可以实现对于多文件的上传了。
关于HTML5上传中的各种需求
虽然上面实现了对于多个文件的上传,但是大家在实际工作中对于上传的需求肯定不单单是能够上传而已,下面我们就来说下利用HTML5对于上传API中新增加的一大堆好用的东西所能够实现的效果;
上传之前的本地预览
大家在做文件上传之前,经常会碰到需要预览文件大小,文件名称等信息,关于这些HTML5已经帮我们封装好了相应的API,我们只需要调用方法即可 上面说到关于<input type="file" />
标签中有一个files数组对象,实际上这个数组对象中的每一个值都有一些相应的属性可以调用
- name – 文件名(不包含路径)
- type – 文件的MIME类型(小写)
- size – 文件的尺寸(单位为字节)
通过调用上面的三个属性就可以获得每一个文件在本地的一些相关信息,相关方法如下
function fileSelected() {
var file = document.getElementById('fileToUpload').files[0]; //获取到上传控件对象files
if (file) {
var fileSize = 0;
if (file.size > 1024 * 1024){
fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
}else{
fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
} document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
}
}
关于FileReader
关于本地的预览,一些文件的相关信息我们都已经可以拿到了,但是假如我想要上传的是一张图片,想要直接本地预览这张图片能不能直接在本地完成呢?答案是可以的,只需要你掌握FileReader这个对象即可
FileReader对象一共有4个方法,其中3个可以读取文件,另一个用来中断读取。无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中。 4个方法分别是:
- readAsBinaryString(file) 将文件读取为二进制编码
- readAsText(file,[encoding]) 将文件读取为文本
- readAsDataURL(file) 将文件读取为DataURL
- abort 中断读取操作
FileReader对象同样也有很多事件,分别是:
- onabort 中断
- onerror 出错
- onloadstart 开始
- onprogress 正在读取
- onload 成功读取
- onloadend 读取完成,无论成功失败
那我们在上面的事件方法基础上就可以实现关于本地预览图片的相关方法:
var reader = new FileReader(); //创建一个FileReader对象
reader.readAsDataURL(file); //将文件以Data URL形式读入页面 ,并且将结果存在result属性中
reader.onload=function(e){ //当文件成功读取后
var imgBox=document.getElementById("imgBox");
imgBox.innerHTML='<img src="' + this.result +'" alt="" />'; //显示文件
}
通过上面的方法就可以实现图片的本地预览了,当然上面那个方法还可以结合之前的files对象中的type,size等属性实现上传图片类型大小的限制。
关于HTML5的上传部分,实际上还有很多应用的地方,将会在以后的博客中告诉大家。
HTML5关于上传API的一些使用(上)的更多相关文章
- HTML5关于上传API的一些使用(中)
上一次写了关于HTML的上传API,XMLHttpRequest2.0的上传方式,以及HTML5中上传之前本地的预览,包括对于图片以及部分信息的预 览.这次我们就讲下HTML5中关于上传的一些各种个性 ...
- HTML5关于上传API的一些使用(下)
通过前面两篇的分享,我们已经搞定了单个文件的普通的上传,包括文件预览,图片预览,上传速度等前端界面的显示,这次我们来谈谈关于>XMLHttpRequest2.0在界面之后假如才用分片上传能做到一 ...
- 优酷视频上传api及demo代码
1,优酷正常上传流程: 1). create:连接开放平台上传接口服务器,服务器端会返回upload_token以及upload_server_uri.2). create_file:连接上传服务器( ...
- php+html5实现无刷新上传,大文件分片上传,断点续传
核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...
- Flash上传组件之SWFUpload文件上传
一.什么是SWFUpload? SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为WEB开发者提供了一个具有丰富功能继而 ...
- .net 实现上传文件分割,断点续传上传文件
一 介绍 断点续传搜索大部分都是下载的断点续传,涉及到HTTP协议1.1的Range和Content-Range头. 来个简单的介绍 所谓断点续传,也就是要从文件已经下载的地方开始继续下载.在以前版本 ...
- Spring Boot2(十四):单文件上传/下载,文件批量上传
文件上传和下载在项目中经常用到,这里主要学习SpringBoot完成单个文件上传/下载,批量文件上传的场景应用.结合mysql数据库.jpa数据层操作.thymeleaf页面模板. 一.准备 添加ma ...
- 文件上传三:base64编码上传
介绍三种上传方式: 文件上传一:伪刷新上传 文件上传二:FormData上传 文件上传三:base64编码上传 Flash的方式也玩过,现在不推荐用了. 优点: 1.浏览器可以马上展示图像,不需要先上 ...
- 微信小程序语音(A)发给别人(B),也能播放,是需要先把语音上传到自己的服务器上才可以
小程序语音(A)发给别人(B),也能播放,是需要先把语音上传到自己的服务器上才可以. https://developers.weixin.qq.com/miniprogram/dev/api/medi ...
随机推荐
- [Compose] 19. Leapfrogging types with Traversable
We use the traversable instance on List to reimplement Promise.all() type functionality. For example ...
- c++初始化函数列表
以下三种情况下需要使用初始化成员列表: 一,需要初始化的数据成员是对象的情况: 二,需要初始化const修饰的类成员: 三,需要初始化引用成员数据: 原因: C++可以定义引用类型的成员变量,引用类型 ...
- 隐函数画图with R
隐函数画图 with R 这个函数 sin(xsiny)-cos(ycosx)=0 图是这个样子 怎么用R画出来呢?下面是代码 x<-y<-seq(-10,20,0.1) f<-fu ...
- SpriteKit改变Node锚点其物理对象位置不对的解决
在创建Node的物理对象后,默认情况下物理对象和Node的实际边界相应的非常好,由于此时Node的默认锚点是当中心位置即(0.5,0.5),只是假设我们改变了Node的锚点,就会发现其物理边界还是保持 ...
- vlc模块间共享变量
在模块中创建变量: vlc_value_t valTemp; var_Create( p_intf, "vlc_test", VLC_VAR_STRING ); valTemp ...
- java注解,通过反射解析注解,模仿hibernate,获取sql语句。
常用注解: 自定义注解,标准格式: 1,target:注解作用域 2,Retention:声明周期 运行子类继承,但是子类继承只能作用到类注解,字段注解,是继承不了的. 使用注解:通过下面这种方式,为 ...
- (二)hibernate进阶
1.hibernate.cfg.xml常用配置以上节代码为例 <session-factory> <property name="connection.username&q ...
- nginx配置用户认证
location ~ .*admin\.php$ { auth_basic "weifenglinux auth"; auth_ba ...
- Percona Toolkit工具集介绍
部署mysql工具是一个非常重要的部分,所以工具的可靠性和很好的设计非常重要.percona toolkit是一个有30多个mysql工具的工具箱.兼容mysql,percona server,mar ...
- 【翻译】Android多线程下安全访问数据库
为了记录如何线程安全地访问你的Android数据库实例,我写下了这篇小小札记.文章中引用的项目代码请点击这里 假设你已编写了自己的 SQLiteOpenHelper. publicclas ...