这篇文章发布于 2017年07月5日,星期三,02:03,归类于 Canvas相关, JS实例。 阅读 141913 次, 今日 25 次 48 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=6252
本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意。
一、HTML与文件下载
如果希望在前端侧直接触发某些资源的下载,最方便快捷的方法就是使用HTML5原生的download
属性,例如:
<a href="large.jpg" download>下载</a>
具体介绍可参考我之前的文章:“了解HTML/HTML5中的download属性”。
但显然,如果纯粹利用HTML属性来实现文件的下载(而不是浏览器打开或浏览),对于动态内容,就无能为力。
例如,我们对页面进行分享的时候,希望分享图片是页面内容的实时截图,此时,这个图片就是动态的,纯HTML显然是无法满足我们的需求的,借助JS和其它一些HTML5特性,例如,将页面元素转换到canvas
上,然后再转成图片进行下载。
但本文要介绍的下载不是图片的下载,而是文本信息的下载,所需要使用的HTML特性不是canvas
,而是其它。
二、借助HTML5 Blob实现文本信息文件下载
如果对Blob不了解,可以先看看我好些年之前写的“理解DOMString、Document、FormData、Blob、File、ArrayBuffer数据类型”一文。
原理其实很简单,我们可以将文本或者JS字符串信息借助Blob转换成二进制,然后,作为<a>
元素的href
属性,配合download
属性,实现下载。
代码也比较简单,如下示意(兼容Chrome和Firefox):
var funDownload = function (content, filename) { // 创建隐藏的可下载链接 var eleLink = document.createElement('a'); eleLink.download = filename; eleLink.style.display = 'none'; // 字符内容转变成blob地址 var blob = new Blob([content]); eleLink.href = URL.createObjectURL(blob); // 触发点击 document.body.appendChild(eleLink); eleLink.click(); // 然后移除 document.body.removeChild(eleLink); };
其中,content
指需要下载的文本或字符串内容,filename
指下载到系统中的文件名称。
万般言语不达意,一枚实例来走心。
您可以狠狠地点击这里:基于funDownload实现的html格式文件下载demo
点击“下载”按钮,会把文本域中的内容全部作为一个.html
后缀文件下载下来,各流程效果如下面几张图:
出现下载确认框(根据浏览器的设置不同也可能直接下载),然后名称默认就是test.html
。
然后对应保存目录就多了个类似下图的文件:
双击该test.html
文件可以在浏览器中正常浏览,说明,保存信息无误。
触发下载的JS代码就几行:
button.addEventListener('click', function () { funDownload(textarea.value, 'test.html'); });
三、借助Base64实现任意文件下载
对于非文本文件,也是可以直接JS触发下载的,例如,如果我们想下载一张图片,可以把这张图片转换成base64格式,然后下载。
代码示意:
var funDownload = function (domImg, filename) { // 创建隐藏的可下载链接 var eleLink = document.createElement('a'); eleLink.download = filename; eleLink.style.display = 'none'; // 图片转base64地址 var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var width = domImg.naturalWidth; var height = domImg.naturalHeight; context.drawImage(domImg, 0, 0); // 如果是PNG图片,则canvas.toDataURL('image/png') eleLink.href = canvas.toDataURL('image/jpeg'); // 触发点击 document.body.appendChild(eleLink); eleLink.click(); // 然后移除 document.body.removeChild(eleLink); };
四、结束语
不止是.html
文件,.txt
, .json
等只要内容是文本的文件,都是可以利用这种小技巧实现下载的。
在Chrome浏览器下,模拟点击创建的<a>
元素即使不append
到页面中,也是可以触发下载的,但是在Firefox浏览器中却不行,因此,上面的funDownload()
方法有一个appendChild
和removeChild
的处理,就是为了兼容Firefox浏览器。
download
属性从Edge13开始支持,理论上,edge也应该支持直接JS触发的浏览器文件下载,但我手头上并无相关浏览器,无法确定真实情况如何,欢迎有条件的小伙伴帮忙测下告知结果。
感谢arrow的反馈:
edge下载完就生成一个文件,类似GUID命名的,加个后缀就正常了。
就这些吧,感谢阅读!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=6252
(本篇完)
- js面向数据编程(DOP)一点分享 (0.513)
- 翻译:ECMAScript 5.1简介 (0.513)
- 基于HTML模板和JSON数据的JavaScript交互 (0.513)
- 简单了解ES6/ES2015 Symbol() 方法 (0.513)
- 纯前端JS zip打包文件并下载 (0.440)
- SVG <foreignObject>简介与截图等应用 (0.304)
- CSS滤镜和混合模式处理的图片如何上传下载? (0.304)
- 了解HTML/HTML5中的download属性 (0.256)
- windows系统下批量删除OS X系统.DS_Store文件 (0.256)
- 学习了,CSS中内联SVG图片有比Base64更好的形式 (0.256)
- 使用CSS将图片转换成模糊(毛玻璃)效果 (RANDOM - 0.047)
鑫哥,URL.revokeObjectURL()需要配合URL.createObjectURL()使用吗?
如果是跨域的 mp4 url 有什么办法直接下载嘛
只要涉及跨域,前端就无法独立解决,所以,你这个问题需要让运维或者后台协助。
1. 让运维代理url地址
2. 让后台下载后,再转发给你
鑫哥这里的宽高没用上,需要用上才能得到完整的图片
var width = domImg.naturalWidth;
var height = domImg.naturalHeight;
你好,用创建blob方法下载下来的文件,打开显示文件损坏是什么问题呢
能否纯前端生成word呢
http:\/\/zhehetest.oss-cn-hangzhou.aliyuncs.com/file/2020/06/03/14期业绩结算单状态码.txt
这个要怎么下载。。。怎么试都下载不下来==
如果后台只给个路径,这个路径可以用浏览器直接打开,
后台也不处理跨域,
怎么才能进行这个文件的下载呢 ,
这是个以 .log为后缀的文件
新建一个页面,然后后台配置下页面的header信息。
请问,纯前端有办法下载视频吗?我们项目之前用的就是前端给后端提供URL,后端根据URL去下载,但是有的视频文件特别大1G左右,就会造成请求超时,下载失败,现在向转到前端自行下载,不知是否可行?还有URL地址和前端项目不在一个服务器上,存在跨域。。
如果是服务器上的静态托管文件呢? 只有url, 怎么才能获取到文件内容呢? 只能通过ajax请求文件url获取到内容吗?
获取可以Ajax,让非跨域的后端曲线救国。
aaaa
苹果手机不支持download
跪求解答,我已经找了好久都不知道苹果手机怎么下载文件
请问移动端,有什么解决方案吗?
旭哥,是canvas.toDataURL(),canvas的context对象没有这个方法,这个方法是canvas节点的。
好的,感谢反馈。
如果在html中引入了外部css和js,怎么下载html的时候连同也下载css和js
Uncaught DOMException: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.
需要图片服务器配置accept header,可参见这篇文章:https://www.zhangxinxu.com/wordpress/2018/02/crossorigin-canvas-getimagedata-cors/
txt中文本的格式是怎么控制的呢,苹果端中下载的txt 格式是对齐的 但是window中txt 就乱了
无解。让用户使用等宽字体?或者直接输出用的HTML。
请问下为什么网络路径就直接在另一个页面打开了呢
怎么解决呢
那么上传呢?就是在本地生成或者本地有一个html文件,然后动态写入内容进行上传。
文件下载似乎不能指定utf-8编码呢,不知道是否有办法在生成的时候指定文件的编码格式呢?求大神解答
请问一下,在移动端好像不行呢,点击没反应,怎么破
你移动端搞定没,求教个
解决了我的问题,点赞
旭哥,是canvas.toDataURL()
怎么在代码里面指定目录,然后自动下载,不用弹框出来进行选择,
那是浏览器的设置吧,或者用浏览器插件也可以
这个办法解决了通过post下载文件的问题,感动涕零
从fetch返回response对象的blob方法可以获取到后端的文件流,then回调的参数就是blob对象,用headers Content-Disposition 可以判断文件名,直接就能下载了,爽到不行
···
response.blob().then((blob) => {
//create donwload
}
···
您好。请问如果我需要下载的是js文件怎么办呢?该js文件内容只是简单的对象嵌套。我尝试改变MIME类型,但发现出来的还是[Object Object]。用JSON转成字符串是可以实现的,但我希望原文下载。需要怎么做呢?
大神,我就想问问,浏览器能做到分片下载大文件?能实现串行下载,一个文件下载完下载另一个文件?
可以,可以直接对文件数据进行slice~
我用浏览器已经测试成功了,能把文件下载下来。到了手机上把文件流读完后就弹出是否下载的对话框,点下载就提示下载失败,也没个下载失败的原因。
太短了
请问一下。IE 有其他方式可以代替实现吗?
这个事儿我没记错的话FileSaver.js就是这么实现的
如果是比较大的文件,如视频、音频文件就没法做了吧?
可不可以把数据库的内容,导成excel格式的
生成了一个叫“A1DEA3AF-8977-4064-A5D8-5B17DC9E44EB”的无后缀文件
张大哥你好,入坑前端以来就一直关注你的博客,平时遇到CSS方面的难题第一个想到的就是打开你的博客看看有没有类似研究,不得不说这方面你已经走在了非常前沿,钻研得很透彻。
最近我遇到一个关于position:fixed 的有趣现象,这里想和你讨教一下。我查阅了国内外能触及到的资料,其定义解释都是,这个属性是元素相对于viewport进行绝对定位。
但是!有趣的是,当我把left的值设置为auto或删掉left属性时,奇迹发生了!该元素竟然位于父元素的最边缘!此处left作为举例,经尝试,right也是同样的效果。
废话不多说,请看代码
链接在此
https://codepen.io/HazelZ/pen/GEGOqv
不知该如何解释这一现象,还请大哥指正
@Hazel 基本常识啦,规范和定义就是如此,绝对定位也是同样的。
edge
下载完就生成一个文件,类似GUID命名的
加个后缀就正常了
旭哥,想知道HTML转canvas,有哪些实现方法呢?我目前只知道一个借助svg的foreignObject来实现的办法
html2canvas插件,可以尝试一下