前面一直做过下载的功能。就是后台将文件流写入response里面,然后就好了。前台会自动弹出下载提示等。
今天打算做一个ajax下载。想当然的结果死活浏览器没反应。我擦。
然后浏览器调试,发现response返回过来的是一串类似乱码的文本而不是二进制文件流。定位原因在这里。
之后继续百度,如何实现ajax异步下载。回答是这样的:
那就是请求方式有问题,文件下载的请求是不能写在ajax里面的!
原因:因为response原因,一般请求浏览器是会处理服务器输出的response,例如生成png、文件下载等,然而ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。文件的下载是以二进制形式进行的,虽然可以读取到返回的response,但只是读取而已,是无法执行的,说白点就是js无法调用到浏览器的下载处理机制和程序。
然后继续百度,我有点不信邪。找到这篇文章:http://www.cnblogs.com/cdemo/p/5225848.html
原来ajax并非只能获取文本而不能获取二进制流,只是jquery封装的ajax的问题。
抱怨:jquery做了这么久了 一个ajax方法还停留在几年前的xmlhttprequest 1的版本中,惊人的不支持流文件!!! 我这还怎么大肆推行我的前后台完全隔离思想~~。算了不抱怨了,果然是不能靠别人,只能自己写了。 楼主依稀记得 xmlhttprequest 2 标准中支持流文件的,并且应该使用 xhr.response作为返回 而不是responseText。
于是使用原生的ajax获取流文件:
var url = serverUrlBase + "/server/images/" + mapid + "/files/png"; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = "blob"; xhr.setRequestHeader("client_type", "DESKTOP_WEB"); xhr.setRequestHeader("desktop_web_access_key", _desktop_web_access_key); xhr.onload = function() { if (this.status == 200) { } } xhr.send();
获取到了文件,然后原贴中需要的操作是展示,使用blob对象。
这样应该可行,但是怎么处理请求的数据呢? ???? 这个问题。 对了 html5新特性里面是不是 提到一个 Blob对象来着。试试看。
通过查阅相关blob资料,查阅 4.6.9 The response
attribute 得知 返回类型应该使用
于是原贴中剩下的是建造img标签,赋值各个属性,结果得到了。
然后我懵逼了,我需要的是下载啊。有点急着要结果,所以我先放开了这种思路。
我记得搜索得到别人的做法是使用一个iframe,得到不刷新原来页面下载的效果,也就是它使用直接其它层直接访问的方式模拟了ajax。发现,真简单:
参考这篇文章:http://www.jb51.net/article/47294.htm
代码:
<script> function download() { //下载文件的地址 var url="http://music.baidu.com/data/music/file?link=http://zhangmenshiting.baidu.com/data2/music/13618994/13618995183600128.mp3?xcode=48d4a720fcd9a974586066d0145f7207"; document.getElementById("ifile").src=url; } </script> <a href="#" onclick="download()">download</a> <iframe id="ifile" style="display:none"></iframe>
区别只是将我的链接替换进去了。
效果达到了,但还有点不死心,轻易得到的东西总是不会珍惜。我还是想看看我的ajax下载。我想啊,我都能在页面得到元素了,为什么我不能下载呢?
于是百度搜索前端js下载
刚好发现了一篇文章:http://blog.csdn.net/greatbody/article/details/70207232
思路:
我已经做好了一半了。剩下下载就是了。于是我模拟它的方法将自己的代码改写了一下。
<script type="text/javascript"> function f() { var url = "/servlet/example"; // document.getElementById("ifile").src=url; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = "blob"; xhr.onload = function() { if (this.status == 200) { var blob = this.response; downloadFile(fileNameFromHeader(xhr.getResponseHeader("Content-Disposition")), xhr.response); } } xhr.send(); } function fileNameFromHeader(disposition) { var result = null; if (disposition && /filename=.*/ig.test(disposition)) { result = disposition.match(/filename=.*/ig); return decodeURI(result[0].split("=")[1]); } return "undefine_file"; } function downloadFile(fileName, content) { var aLink = document.createElement('a'); var blob = new Blob([content]); var evt = document.createEvent("MouseEvents"); evt.initEvent("click", true, true); if (fileName) { aLink.download = fileName; } aLink.target = "_blank"; aLink.href = URL.createObjectURL(blob); aLink.dispatchEvent(evt); } </script>
注意它前端下载的代码:
function downloadFile(fileName, content) { var aLink = document.createElement('a'); var blob = new Blob([content]); var evt = document.createEvent("MouseEvents"); evt.initEvent("click", true, true); if (fileName) { aLink.download = fileName; } aLink.target = "_blank"; aLink.href = URL.createObjectURL(blob); aLink.dispatchEvent(evt); }
创建一个a连接,a链接的地址为要访问的对象,这里是我们的Blon对象,然后js点击,在新窗口。