【前端】利用ajax实现伪文件异步上传下载
2015-11-25 15:20
609 查看
利用ajax可以实现很酷的效果,在不刷新页面的情况下提交表单、修改数据状态等等,可是如果表单里还有input:file可就惨了,ajax不支持文件的处理啊!
ajax是使用了浏览器内部的XmlHttpRequest对象来传输XML数据的。既然是Xml的数据传输,那么传输的数据肯定是文本的,而文件上传则需要传输二进制的数据,显然用ajax是不可能的。
可是ajax这么好用,大家也都习惯了这种开发和使用体验,试想如果form表单包含文件上传,那提交表单要刷新整个页面,提交成功还好,提交失败了表单数据可都没有了,这颗真难受。有没有什么办法能实现类似的逻辑呢?
请注意以下属性:form:target、iframe、parrent.callback() ,我们利用这些小属性,来完成伪·ajax上传下载文件吧。
上边是html的大致结构,form表单包含了input:file,target到一个隐藏的iframe,这个隐藏的iframe并没有做任何事情,最后是一个接受回调的函数叫callback。
接下来就是服务器这边的逻辑了。
/upload这个接口接收到请求之后,从request里获取上传文件,名字就是input的name,然后进行逻辑处理,最后返回html数据。
接下来重点来了:
response返回的时候需要设置ContentType:text/html;charset=UTF-8;并且把结果拼成js代码写入返回的流中。
注意到返回的js片段,调用了parrent的callback函数。
这里的结果会返回到我们之前的隐藏iframe中,parent就是html主页面,callback就是我们提前写好的回调函数。
到这里,关于文件上传的技巧就说完了,接下来讲讲关于文件下载的问题。
关于文件下载,我在工作当中遇到最多的场景就是在xx后台,有一堆查询条件,查询结果按表格展示,然后另外有个单独的按钮叫做“导出”,讲讲怎么使导出功能更加优雅。
首先,按了导出按钮之后server会进行对应的逻辑处理拿数据,之后把数据写到返回里,这中间一旦出现问题就只能返回错误的提示信息了。
这个逻辑有没有跟上边上传的情形很像呢? 我们利用类似的逻辑,来实现带错误提示的文件下载。
首先先上html代码片段
代码分三部分,第一部分是查询表单,有一些查询参数,两个按钮分别是查询和导出。第二部分是一个隐藏的iframe,作用跟最上边的例子一样。第三部分是js代码,包含了3个方法,第一个定义查询按钮的行为-重置了form的target和action,第二个定义了导出的target和action,最后是接收回调的函数
请求到了服务器之后进行处理,查询逻辑就走查询的流程,把数据返回后展示到页面;导出的话有3种可能,有数据、没有数据、出现异常,如果要把状态都反馈到前端,那么这么做试试:
首先,异常和没有数据的情况,都可以按上传文件的返回方式,把处理结果的状态和信息封装到js片段,通过parent.callback返回前端。
如果有数据,那么需要在服务器端把数据写入返回流,并且把response的contentType置为application/x-download,代码示意
这样如果有数据,前端收到请求之后就会走浏览器的下载流程,如果没有数据或者出现异常,可以在不刷新页面的情况下给出提示。
注:以上代码的后端逻辑是以java为基础的伪代码,需要转化下才能真正使用
ajax是使用了浏览器内部的XmlHttpRequest对象来传输XML数据的。既然是Xml的数据传输,那么传输的数据肯定是文本的,而文件上传则需要传输二进制的数据,显然用ajax是不可能的。
可是ajax这么好用,大家也都习惯了这种开发和使用体验,试想如果form表单包含文件上传,那提交表单要刷新整个页面,提交成功还好,提交失败了表单数据可都没有了,这颗真难受。有没有什么办法能实现类似的逻辑呢?
请注意以下属性:form:target、iframe、parrent.callback() ,我们利用这些小属性,来完成伪·ajax上传下载文件吧。
<!-- 这是数据表单 --> <form action="/upload" id="form1" method="post" enctype="multipart/form-data" target="hidden_frame"> <input type="file" name="uploadfile" accept="*" /> <input type="submit" value="提交" /> </form> <!-- 这是一个隐藏的iframe --> <iframe name="hidden_frame" id="hidden_frame" style="display:none;"></iframe> <script type="text/javascript"> // 这是接收回调的函数 function callback(status, message) { alert(message); } </script>
上边是html的大致结构,form表单包含了input:file,target到一个隐藏的iframe,这个隐藏的iframe并没有做任何事情,最后是一个接受回调的函数叫callback。
接下来就是服务器这边的逻辑了。
/upload这个接口接收到请求之后,从request里获取上传文件,名字就是input的name,然后进行逻辑处理,最后返回html数据。
接下来重点来了:
response返回的时候需要设置ContentType:text/html;charset=UTF-8;并且把结果拼成js代码写入返回的流中。
response.setContentType("text/html;charset=UTF-8"); // status表示处理结果的状态码,message为对应的提示信息 response.getWriter().print("<script>parent.callback(status, message);</script>");
注意到返回的js片段,调用了parrent的callback函数。
这里的结果会返回到我们之前的隐藏iframe中,parent就是html主页面,callback就是我们提前写好的回调函数。
到这里,关于文件上传的技巧就说完了,接下来讲讲关于文件下载的问题。
关于文件下载,我在工作当中遇到最多的场景就是在xx后台,有一堆查询条件,查询结果按表格展示,然后另外有个单独的按钮叫做“导出”,讲讲怎么使导出功能更加优雅。
首先,按了导出按钮之后server会进行对应的逻辑处理拿数据,之后把数据写到返回里,这中间一旦出现问题就只能返回错误的提示信息了。
这个逻辑有没有跟上边上传的情形很像呢? 我们利用类似的逻辑,来实现带错误提示的文件下载。
首先先上html代码片段
<!-- 查询表单 --> <form action="/search" method="post" id="searchForm"> <input name="query1" type="input" /> <input name="query2" type="input" /> <input type="button" id="search" value="查询" /> <input type="button" id="export" value="导出" /> </form> <!-- 隐藏的iframe --> <iframe name="hidden_frame" id="hidden_frame" style="display:none;"></iframe> <script type="txt/javascript" src="jquery-1.11.3.min.js"></script> <script type="text/javascript"> $('input#search').bind('click',function(){ $('#searchForm').attr('action',''); $('#searchForm').attr('target',''); $('#searchForm').submit(); }) $('input#export').bind('click',function(){ $('#searchForm').attr('action','/export'); $('#searchForm').attr('target','hidden_frame'); $('#searchForm').submit(); }) // 这是接收回调的函数 function callback(status, message) { alert(message); } </script>
代码分三部分,第一部分是查询表单,有一些查询参数,两个按钮分别是查询和导出。第二部分是一个隐藏的iframe,作用跟最上边的例子一样。第三部分是js代码,包含了3个方法,第一个定义查询按钮的行为-重置了form的target和action,第二个定义了导出的target和action,最后是接收回调的函数
请求到了服务器之后进行处理,查询逻辑就走查询的流程,把数据返回后展示到页面;导出的话有3种可能,有数据、没有数据、出现异常,如果要把状态都反馈到前端,那么这么做试试:
首先,异常和没有数据的情况,都可以按上传文件的返回方式,把处理结果的状态和信息封装到js片段,通过parent.callback返回前端。
response.setContentType("text/html;charset=UTF-8"); // status表示处理结果的状态码,message为对应的提示信息 response.getWriter().print("<script>parent.callback(status, message);</script>");
如果有数据,那么需要在服务器端把数据写入返回流,并且把response的contentType置为application/x-download,代码示意
response.setContentType("application/x-download"); // 描述,filename字段可以设置导出文件的名字,注意URLEncode处理下才可以支持中文 response.setHeader("Content-Disposition","attachment;filename=exportfilename"); // status表示处理结果的状态码,message为对应的提示信息 OutputStream stream = response.getOutputStream(); // infobytes是需要导出的数据 byte[] infobytes = new byte[100]; stream.write(infobytes); stream.flush();
这样如果有数据,前端收到请求之后就会走浏览器的下载流程,如果没有数据或者出现异常,可以在不刷新页面的情况下给出提示。
注:以上代码的后端逻辑是以java为基础的伪代码,需要转化下才能真正使用
相关文章推荐
- jQuery 事件
- Bootstrap历练实例:基本输入框组
- js+ajax读取txt
- 纯css3绘制扇形
- Bootstrap历练实例:输入框组的大小
- bootstrap历练实例:复选框或单选按钮作为输入框组的前缀或后缀
- HTML5入门(2)
- Java NIO (五) Channel to Channel Transfers
- 常用的107条Javascript
- bootstrap历练实例:按钮作为输入框组前缀或后缀
- css3动画简介以及动画库animate.css的使用
- HTML5吧
- jquery插件下载地址
- bootstrap学习和使用的经验总结
- 深入浅出 React Native:使用 JavaScript 构建原生应用
- 搜索input 和提交按钮input 紧紧挨着的CSS效果
- js 获取 根目录
- jQuery 选择同时包含两个class的元素
- javascript跑马灯写法-瞬间高大上了
- jquery之ajax请求工具类