设为首页 收藏本站
查看: 1008|回复: 0

[经验分享] 使用nodejs将html5 canvas base64编码图片保存为文件

[复制链接]

尚未签到

发表于 2017-2-22 09:50:28 | 显示全部楼层 |阅读模式
目前流行的“你画我猜”应用,你有没有想过使用HTML5来实现过?那么不可避免的需要解决canvas保存图片到硬盘或mongodb之类的数据库。本文主要介绍使用nodejs将html5 canvas base64编码图片保存为文件,同时提供两种解决方案。
html5 canvas属于客户端API,没有权限去保存图片到硬盘,只有canvas . toDataURL()这一个接口可导出画布的base64编码,以提供给服务端进行处理保存,据我所知.net和php都有方法或类来进行简单的处理保存。nodejs呢?是的,没错!nodejs同样有能力来保存base64编码的图片。
解决方案一:
使用new Buffer来创建对应编码的缓冲,通过fs模块将Buffer写成一个文件。
优点:简单易用,无需其它模块的支持。
缺点:不能对图片的尺寸,水印,压缩,格式等进行处理。
注意点:
1、new Buffer接收到base64编码,不能带data:URL,而使用canvas . toDataURL()导出的base64编码会带data:URL,所以需要先过滤掉
类似这样的一段“data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0”
需过滤成:“iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0”
2、’binary’ – 一种只使用每个字符前8个字节将原始的二进制数据编码进字符串的方式。这个方式已经废弃,应当尽量使用buffer 对象。这个编码将会在未来的node 中删除。
看到有人把base64声明的Buffer再转换成binary,这个是完全没必要的。
3、生成的图片有size变化,但是打开后是一个无效的图像,这个看本文的第三点。
使用express搭建的/upload (POST)上传保存接口,完成代码如下:

var express =require('express');var fs =require("fs");var app =module.exports = express();//配置
app
.configure(function(){
app
.use(express.bodyParser());
app
.use(express.methodOverride());
app
.use(express.cookieParser('keyboard cat'));
app
.use(express.session());
app
.use(app.router);
app
.use(express.static(__dirname +'/up'));//静态文件目录
app
.use(express.errorHandler({ dumpExceptions:true, showStack:true}));});//保存base64图片POST方法
app
.post('/upload',function(req, res){//接收前台POST过来的base64var imgData = req.body.imgData;//过滤data:URLvar base64Data = imgData.replace(/^data:image\/\w+;base64,/,"");var dataBuffer =newBuffer(base64Data,'base64');
fs
.writeFile("out.png", dataBuffer,function(err){if(err){
res
.send(err);}else{
res
.send("保存成功!");}});});if(!module.parent){
app
.listen(8000);
console
.log('Express started on port 8000');}
解决方案二:
使用node-canvas模块进行图片处理和保存。
(node-canvas安装见我的另一篇博文:http://www.2fz1.com/?p=246)
优点:能对图片像html5 canvas一样进行处理,尺寸调整、水印、图片反转色、格式转换
缺点:需安装模块支持、当base64编码有误不能解析成图片时会报错并停止nodejs服务。
注意点:canvas透明背景,默认为黑色;使用base64给img.src赋值时,需带上data:URL
使用express搭建的/upload (POST)上传保存接口,完成代码如下:

varCanvas=require('canvas');//需安装canvas模块var express =require('express');var fs =require("fs");var app =module.exports = express();//配置
app
.configure(function(){
app
.use(express.bodyParser());
app
.use(express.methodOverride());
app
.use(express.cookieParser('keyboard cat'));
app
.use(express.session());
app
.use(app.router);
app
.use(express.static(__dirname +'/up'));//静态文件目录
app
.use(express.errorHandler({ dumpExceptions:true, showStack:true}));});
app
.post('/upload',function(req, res){var base64Data = req.body.imgData;var img =newCanvas.Image;
img
.onload =function(){var w = img.width;var h = img.height;var canvas =newCanvas(w, h);var ctx = canvas.getContext('2d');
ctx
.drawImage(img,0,0);varout= fs.createWriteStream(__dirname +'/crop.jpg');var stream = canvas.createJPEGStream({
bufsize
:2048,
quality
:80});
stream
.on('data',function(chunk){out.write(chunk);});
stream
.on('end',function(){out.end();
res
.send("上传成功!");});}
img
.onerror =function(err){
res
.send(err);}
img
.src = base64Data;});if(!module.parent){
app
.listen(8000);
console
.log('Express started on port 3000');}
容易出现的错误(base64编码中,不容忽视的“+”号)
1、如果canvas没有任何像素,则返回值为:“data:,”,这是最短的data:URL,代码中最好做一下保护。
2、使用解决方案一实现图片保存,生成的图片有size,但是打开后却是不能识别的无效图像。
使用解决方案二实现图片保存,nodejs直接报错,并且服务挂掉。
原因:
这个问题,花了我很长时间才找到原因,根本原因是base64编码,使用express接收POST值后,base64编码字符串中的“+”号被替换成空格了,引起编码出错,img.src = base64Data;直接把nodejs服务挂掉。如果你出现类似问题,请console.log(base64Data);看字符串是否有空格。
解决办法:
将空格替换回“+”号

var base64Data = imgData.replace(/\s/g,"+");

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345536-1-1.html 上篇帖子: 借助Nodejs在服务端使用jQuery采集17173游戏排行信息 下篇帖子: 用nodejs访问ActiveX对象,以操作Access数据库为例。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表