前文中我们聊了 Data URI 和 base64编码,稍微回顾下。base64编码 是将数据用 64 个可打印的字符进行编码的方式,任何数据底层实现都是二进制,所以都可以进行 base64编码,base64编码 主要用在数据传输过程中(编码、解码)。而 Data URI 是将数据用 URI 的形式进行展现。常用的是将图片进行 base64 编码,用 Data URI 的形式进行展现,可以说,base64编码后的字符串是某些 Data URI(这里就包括图片的 base64 URL) 的一部分。(图片转 Base64码 之后是通过 Data URI scheme来实现显示的)
那么,如何获取一张图片 base64 编码后的数据呢?Data URI 应用场景小结 的最后我们给出了几个链接,如果不能上网,我们可以用如下几种方法试试。
我们以 这张图 为例,它的 base64编码为:
复制代码 data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7
chrome
打开 chrome 浏览器,将图片拖入浏览器中,打开调试面板(F12),在 Sources 栏下即可看到该图片的 base64编码 字符串。
PHP
很多语言都有内置的 base64 encode 以及 decode 函数。比如 PHP 里有 base64_encode()
函数:
复制代码- <?php
- $file = "1.gif"; // 文件路径
- if($fp = fopen($file, "rb", 0)) {
- $binary = fread($fp, filesize($file)); // 文件读取
- fclose($fp);
- $base64 = base64_encode($binary); // 转码
- echo $base64; // 显示base64码
- }
- ?>
echo 出来的东西就是图片的 base64 编码。
File API
2016.07.31 补
详细可以参考 HTML5 File API — 让前端操作文件变的可能 一文
demo 地址 http://hanzichi.github.io/2016/image2base64/
Canvas
canvas 有内置的 toDataURL()
方法,可以将
canvas 图像转换为 Data URI 格式的字符串。其实这个过程有两步,首先把图像转成 PNG 数据,然后再把得到的二进制的 PNG 数据转成纯 ASCII 的 base64 编码的字符串。(将图像转化为Base64字符串的原理或者过程是什么)
将需要编码的图片 "弄" 到 canvas 上可以用 drawImage()
API。
复制代码- var img = new Image();
- img.onload = function() {
- var canvas = document.createElement('canvas');
- canvas.height = img.height;
- canvas.width = img.width;
- var ctx=canvas.getContext("2d");
- ctx.drawImage(img, 0, 0);
- console.log(canvas.toDataURL()); // 输出 Data URI
- }
- img.src = '1.gif';
但是该方法与前两种获取的 base64 编码不一样,我猜想应该是 canvas 图像转 png 图像时改变了 MiME TYPE 所致,那么显然 base64码 也不一样了。但是如果用 png 图的话也是一样结果,所以可以判断将一张 png图 用 drawImage API 附到 canvas 上,然后再用 toDataURL() 转为 png 的过程中,其实已经是两张不同的 png 图了。
所以 canvas 转换法其实并不可靠。
后续思考:本来我是想做个简单的 demo 实现,但是无法获取上传文件的绝对路径地址,如果用 file 控件的话会显示 fakepath,如 "C:fakepath1.png",原因也很好理解,如果上传文件能获取该文件在用户 PC 上的路径的话,那么岂不是泄露了用户隐私?用 PHP 的话可以考虑先将文件传到服务器,然后进行 base64 的编码,不过服务器得是自家的,用免费的服务器显然不行(405 Not Allowed)。后续可以考虑用 fileReader 试试。