1、环境配置

开发语言:php+H5
框架:thinkPHP3.2+WeUI
服务器:阿里云centos7(客户主机是WD的Windows虚拟主机)

2、场景描述

最近在做微信公众号的全栈开发,涉及到一个图片上传水印的功能。因为使用的是tp框架,所以其实框架内部里面集成好了一些很方便的图片处理的工具类,只要开启php相关扩展就好了。但是由于虚拟主机受限,加上服务器性能较差,因此决定在网页前端使用H5的一些API来进行图片的处理。
说到这里,其实我应该去对比一下后端与前端处理的速度和性能的,还有一点就是如果使用后端来处理图片的话,那么对兼容性的要求就低了很多,前端只要负责显示、预览图片就好了。

3、注意

还有很重要的一点,这样做只能在每次选择一张图片的时候进行水印的添加,如果是ios或者桌面那种,一次性可以添加多张图片的话,批量加水印就没办法做了。而且据我实现,去除水印这个功能,压缩很快,所以加载水印这个还是挺耗时的。
体验地址:上传demo

4、具体实现

1、上传容器创建

创建一个上传的input标签,capture属性的设置是用来解决在安卓机器中上传图片无法调起手机拍照工具的问题,IOS并没有这个问题。accept设置文件的类型,此处设置为所有图片格式。

<input id="uploaderInput" class="weui_uploader_input" type="file" accept="image/*" multiple="" capture="camera">

2、图片压缩

图片压缩使用的是https://github.com/think2011/localResizeIMG的插件(感恩开源)。操作简单,设备兼容性还不错。

//这里的file是一个图片文件对象,可以使用files属性去获取input内的图片的对象。
lrz(file,{width:640,quality:0.5}).then(function (rst) { //do somethingvar newBaseCode = rst.base64})

压缩成功后,重新获取图片的base64的编码值。其实原理就是通过canvas对图片进行一系列裁剪缩放等操作。主要难点是处理移动端设置的兼容性。

3、图片加水印

因为我们通过上诉压缩工具得到的是图片的base64的编码,但是要对图片进行水印操作,那么需要得到图片的长宽的具体参数,因此我们就需要把base64转成一张图片,

//处理已经压缩完毕得到的图片文件(注意不是base64编码)canvas = document.createElement('canvas');canvas.height = img.height;canvas.width = img.width;var ctx = canvas.getContext("2d");ctx.drawImage(img,0,0);ctx.font = "20px microsoft yahei";ctx.fillStyle = "rgba(255,255,255,0.5)";ctx.fillText(siteTitle,30,30);var dataUrl = canvas.toDataURL();//base64文件rst_files.push({"rst_64":dataUrl});
//新建一个图片对象var img = new Image();var rst_url = convertBase64UrlToBlob(rst.base64);if (url) {src = url.createObjectURL(rst_url);} else {src = e.target.result;}
//给图片设置src属性img.src = src;
//base64转filefunction convertBase64UrlToBlob(urlData){var bytes=window.atob(urlData.split(',')[1]);        //去掉url的头,并转换为byte//处理异常,将ascii码小于0的转换为大于0var ab = new ArrayBuffer(bytes.length);var ia = new Uint8Array(ab);for (var i = 0; i < bytes.length; i++) {ia[i] = bytes.charCodeAt(i);}return new Blob( [ab] , {type : 'image/png'});}

这里有一个很重要的地方就是,image.onload一定要写在img.src的前面,因为这样onload才会生效。具体原因自行google。

4、献上上传的完整代码

<script>$(function(){var name,phone,miaomuId;var rst_files = [];var i,src_ori;var canvas;var tmpl = '<li class="weui_uploader_file" style="background-image:url(#url#)"></li>',$gallery = $("#gallery"), $galleryImg = $("#galleryImg"),$uploaderInput = $("#uploaderInput"),$uploaderFiles = $("#uploaderFiles");$uploaderInput.on("change", function(e){var src, url = window.URL || window.webkitURL || window.mozURL, files = e.target.files;
//            console.log(rst_files);
//            console.log(rst_files.length);if(rst_files.length>8){$.alert('最多上传9张图片',siteTitle);return false;}
//            console.log(files);for (var i = 0, len = files.length; i < len; ++i) {var file = files[i];console.log(i);//图片加水印var img = new Image();img.onload=function () {console.info('onload');if(this.complete){canvas = document.createElement('canvas');canvas.height = img.height;canvas.width = img.width;var ctx = canvas.getContext("2d");ctx.drawImage(img,0,0);ctx.font = "20px microsoft yahei";ctx.fillStyle = "rgba(255,255,255,0.5)";ctx.fillText(siteTitle,30,30);var dataUrl = canvas.toDataURL();//base64文件
//把所有的base64编码的图片存储如一个json数组中。切记这边要用双引号,规范!!!rst_files.push({"rst_64":dataUrl});}console.log(rst_files);}//压缩并且准备添加水印console.info(file);lrz(file,{width:640,quality:0.5}).then(function (rst) {console.info(file);var rst_url = convertBase64UrlToBlob(rst.base64);if (url) {src = url.createObjectURL(rst_url);} else {src = e.target.result;}img.src = src;console.info('src'+i);});if (url) {src_ori = url.createObjectURL(file);} else {src_ori = e.target.result;}$uploaderFiles.append($(tmpl.replace('#url#', src_ori)));}});$uploaderFiles.on("click", "li", function(){$galleryImg.attr("style", this.getAttribute("style"));$gallery.fadeIn(100);});$gallery.on("click", function(){$gallery.fadeOut(100);});//base64转filefunction convertBase64UrlToBlob(urlData){var bytes=window.atob(urlData.split(',')[1]);        //去掉url的头,并转换为byte//处理异常,将ascii码小于0的转换为大于0var ab = new ArrayBuffer(bytes.length);var ia = new Uint8Array(ab);for (var i = 0; i < bytes.length; i++) {ia[i] = bytes.charCodeAt(i);}return new Blob( [ab] , {type : 'image/png'});}
//        上传$('#upload').on('click',function () {console.log(rst_files);miaomuId = {$id};name = $('#name').val();phone = $('#phone').val();if(name == ''){$.alert('请填写姓名',siteTitle);return false;}if(phone == ''){$.alert('请填写联系电话',siteTitle);return false;}if(checkMobile(phone) === false){$.alert('手机号码格式有误,请重新输入',siteTitle);return false;}function checkMobile($tel){if(!(/^1[3|4|5|7|8][0-9]\d{4,8}$/.test($tel))){return false;}}if($uploaderInput[0].files.length == 0){$.alert('请选择要上传的图片',siteTitle);return false;}var param = {'name':name,'phone':phone,'miaomuId':miaomuId,'rst':rst_files};console.log(param);$.showLoading('上传中...');$.ajax({
//                TODO 替换jrmmurl: 'your url',type: 'POST',data: param,
//                cache: false,
//                processData: false,
//                contentType: false,success:function (response) {$.hideLoading();console.log(response);$.alert(response.reason,siteTitle);},error:function () {$.alert(serverError,siteTitle);}});})});
</script>

5、后端处理

部分关键代码

<?php $base64Arr = $_POST['rst'];$miaomuId = I('miaomuId');$name = trim(I('name'));$phone = I('phone');$openid = session('openId');if(!$miaomuId || !$name || !$phone || !$openid){$output = outputHandler(null,0,'图片上传失败');$this->ajaxReturn($output);}$picModel = D('PicRecord');$saveRes = $this->saveImgHandler($picModel,$base64Arr,$miaomuId);//图片上传处理
private function saveImgHandler($picModel,$base64Arr,$miaomuId = 0){//        $picModel = D('PicRecord');$urlList = array();$uuChar= 'A';//保存上传的图片foreach ($base64Arr as $file){$uuChar .= 'A';$type_limit = array('jpg','jpeg','png');if(preg_match('/data:\s*image\/(\w+);base64,/iu',$file['rst_64'],$tmp)){if(!in_array($tmp[1],$type_limit)){return outputHandler(null,0,'图片格式不正确,只支持jpg,jpeg,png!',200);}}else{return outputHandler(null,0,'上传失败,请重新再试!',200);}$img = str_replace(' ','+',$file['rst_64']);$img = str_replace($tmp[0], '', $img);
//对上传的base64编码进行处理后$hi = base64_decode($img); //解码$rootPath = './Uploads/Home/'; //设置文件上传路径$destination = $rootPath.date('Ym').'/'.date('d').'/';//创建文件夹!is_dir($destination) && mkdir($destination, 0755, true);$filename = md5(session('openId').time().$uuChar).'.jpg';.//设置文件的名称file_put_contents($destination.$filename,$hi);//存储图片$urlList[] = $picModel->saveUploadImgs(''.ltrim($destination,'.').$filename,$miaomuId);}return $urlList;}
?>

H5多图片压缩加水印上传相关推荐

  1. java图片加水印上传工具类_基于Spring Boot实现图片上传/加水印一把梭操作

    文章共537字,阅读大约需要 2分钟 ! 概述 很多网站的图片为了版权考虑都加有水印,尤其是那些图片类网站.自己正好最近和图片打交道比较多,因此就探索了一番基于 Spring Boot这把利器来实现从 ...

  2. ASP.NET给图片加水印——上传文件

    在上一篇文章介绍了指定图片文件,给指定的文件添加水印 在本文中将加水印应用于项目中,在用户上传图片文件时,为图片加相应的水印 仍然使用一般处理程序(.ashx) 用户都是通过上传控件,将图片文件添加进 ...

  3. java 图片压缩加水印_java图片添加水印和压缩

    图片添加水印和压缩 [Java]代码 package net.leebao.core.util; import java.awt.AlphaComposite; import java.awt.Col ...

  4. java 压缩图片时候加水印

    直接上代码: 图片压缩加水印 @Testpublic void TetsShuiYin() {// String path1 = "D:\\temp\\Flower.PNG"; / ...

  5. uniapp - 超详细 H5 网站图片压缩功能,图像上传前进行压缩降低大小并上传到服务器完整示例源码(附带 uview 组件库 u-upload 上传组件与该图片压缩插件 “搭配组合“ 使用教程)

    前言 网上的文章代码非常乱,各种无注释及平台不通用的问题,根本无法改造为自己想要的效果. 本文站在小白的角度,从 0-1 详细描述了 uniapp H5 网页平台下,图片上传前 "压缩降低大 ...

  6. js图片前端压缩多图上传(旋转其实已经好了只是手机端有问题要先压缩再旋转)...

    var filechooser = document.getElementById("choose");// 用于压缩图片的canvasvar canvas = document. ...

  7. H5图片预览及上传(WEB前端)

    H5图片预览及上传 web上传图片很简单,网上有许多的demo和js,但是本人嫌弃用那些会引入许多js包,所以还是用原生的jquery来写吧. 一.html布局文件 html有一个自己的上传文件控件- ...

  8. 无水印上传本地图片到网络获取地址+小书匠使用 +github和 七牛云 图床绑定--菜鸟小回

    无水印上传本地图片到网络获取地址+小书匠使用 +github和 七牛云 图床绑定 简介: 最近开始写博客,缺少一个Markdown编辑器.寻找了两三天终于找到了这款<小书匠>,可复制粘图, ...

  9. 图片怎么加水印?添加水印其实很简单

    图片怎么加水印?相信很多作摄影师的小伙伴们都会在日常的分享中给自己的照片添加水印.我们都知道拍摄一张出色的照片背后付出了很多,给图片添加水印是对自己照片版权的保护.那么问题来了,如何好看的添加水印呢? ...

最新文章

  1. Druid数据库连接池超时问题com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 1000, active 10
  2. mysql支持asp.net_关于Mysql + asp.net注射能支持多语句的感慨(2月)
  3. HTML 元素居中的方法
  4. Minimal安装CentOS 7使用yum报This system is not registered to Red Hat Subscription Management.
  5. XCode中设置字体大小
  6. ntfs安全权限和共享权限的区别
  7. 计算机对口高考文化试卷,计算机对口高考模拟试卷
  8. 在windows系统和linux系统中查询IP地址命令的不同
  9. c语言中typeof关键字
  10. android 触摸事件 控制,Android笔记:触摸事件的分析与总结----TouchEvent处理机制
  11. [转]我对CTO的理解
  12. 电脑装服务器系统没有网卡驱动,安装win10系统后没有网卡驱动的解决方法
  13. CISSP国际注册信息系统安全专家
  14. Docker命令(二)
  15. sox处理mp3_音频处理利器--SoX
  16. 知道ip获取计算机密码,知道iP地址怎么获取密码
  17. python最简单的爬取邮箱地址_python小脚本-提取邮箱
  18. html添加启动项,电脑BIOS启动项怎么设置?bios设置启动项图解
  19. phpwind database.php,解决phpwind帖子列表显示个数不正确
  20. CSS进阶式-附加样式

热门文章

  1. Python class调用函数
  2. JINZHIZHUANHUAN
  3. Python GIL锁问题探究及解决
  4. 华为笔试题———个公司做团建活动,排成1个M行N列的队形...请按报数顺序输出特战队员的编号列表(N*2的二维数组)
  5. Instagram 的平台架构和扩展
  6. C# 随机生成3个字的名字
  7. java接收meta name=_java_java实现获取网站的keywords,description,获取网站的meta name=keywords - phpStudy...
  8. 通常来讲,要制定一个清晰的、可执行的计划,需要遵循 SMART原则
  9. java调用dll 动态链接库(dll)初始化例程失败._动态链接库(DLL)初始化例程失败,是怎么回事?...
  10. Project2013工期小数点问题