2019年12月

项目中有个功能需求,对部分图像的浏览做鉴权。未授权前能粗略分辨照片但又要保证原图不被下载保护私隐。虽然一行CSS也可能做到模糊效果,但这种处理手法手略懂前端知识的人可以轻易绕过。所以比较慎重的做法还是后端先对图像预先处理。

把需求进一步简单推理概括的话,就是给图像加上马赛克或做模糊处理。脑子里有个2个比较相似方案。

方案1. 对图像加工(缩小)成仅满足前端显示需要的尺寸,对全图加马赛克处理;
方案2. 对图像加工成更小(大约60x60)的小缩略图,在前端做拉伸覆盖显示,像素在浏览器端拉扯成马赛克(我还真是个逻辑鬼才)

原图(blog做了resize):

org.jpg

方案一加马赛克:

DSC02514.1.JPG

方案二缩小成图标大小再拉伸平铺

构思初步成型,顺便也来比较一下两种做法的处理效率。


- 阅读剩余部分 -

少量中文通过GET方式传参,到了PHP端解码出现乱码或内容丢失。
原因及解决办法

url参数会对 编码字串内的 + 号解释为空格,所以在 decode 之前做一下逆操作就可以解决。

$str_b64 = $_GET["msg"]; //base64编码的字符串
$str_b64 = str_replace(" ","+",$str_b64);
$str_raw = base64_decode($str_b64); //解码

最近摸索前端canvas画布和后端图像加工相关的一些功能。写了个练手程序,为了让前端(js控制css)预览的体验与后端php图像处理一致。总结了几点经验。

先上成品,表情包生成器:
https://gen8.orz.com.cn/mymeme
QQ截图20191227142153.png

img11.jpg

*此文并非系统且科普的教学,讲述的内容基于我个人备忘比较跳跃和零散。

目标:

  1. 用户上传模板图
  2. 在图上画出一个录入文字的涂鸦区域(定义尺寸、位置、文字大小、角度),并可以预览效果
  3. 保存成方案,之后可以打开与分享这个方案。把输入的文字(段子)合成到图片上
  4. 根据涂鸦区域的大小与文字的多与少,一定范围内自动调节文字的大小(未做更换字体、颜色)

这几个目标遇到问题较多的是预览前端的涂鸦区预览 与 后端生成图片的一致性。



- 阅读剩余部分 -

某计费系统出了bug 出现了一批异常扣费记录,影响部分用户的余额。
需要找出异常的扣费记录不难,但不同用户的异常金额是不一样的。
因此无法简单用 'update set blance += patch_value ' 的方式划一校正。

方案一:研究SQL语法有没有办法 UPDATE 嵌套子查询,使每个用户发的 更新值不一样,发现这样写sql语句的逻辑繁琐语义风险高,抛弃!

方案二:用python或php脚本,先把异常扣费记录查出并根据用户统计,然后再逐个用户执行update。虽然可行,但补丁脚本怕被重复执行且执行后无事务可查不可逆,在业务层面并不理想,属于粗暴操作,也没有采用。

方案三:最终方案。计费记录表新增了一个对DELETE事件的触发器(trigger),当删除记录时将扣费的金额归还到用户的余额。这样做的好处是修正的余额由mysql内部逻辑实现。而且将来其他情况下需要对异常记录撤销也能满足余额自动返还。不用人为用写程序干预。

实现步骤

0.首先备份原数据

此步骤非必须,只是作为保险在进行操作前对相关数据进行备份,万一出现严重错误仍可把备份表还原。

#复制表结构
CREATE TABLE `paylog_bak` LIKE `paylog`; 

#复制数据
INSERT INTO `paylog_bal` (SELECT * FROM `paylog`);

1. 创建 trigger

CREATE TRIGGER `refund` 
AFTER DELETE ON `paylog`FOR EACH ROW 
    UPDATE `customer` 
    SET `balance` = `balance` + OLD.`amount` 
    WHERE `id` = OLD.`cid`

sql解读:
创建一个名为 refund (退款) 的触发器,当 paylog 发生 删除事件时
将删除行的支付金额(amount),增加到对应的客户表(customer)的余额(balance)

2. 删除异常的记录

此处sql略,根据异常数据的特征 DELETE FROM paylog WHERE .... 就行。执行后检查受影响的用户余额都有变化。

需求完美实现

此问题常出现在 MySQL 5.7.x 及以后版本(lnmp安装后的默认配置),解决方法备忘如下:

第一步,查看当前 mysql 的变量,运行

SELECT @@GLOBAL.sql_mode;

当中应包含 ONLY_FULL_GROUP_BY

第二部,运行以下这行声明变量(把上一段显示出来的照搬,去掉 ONLY_FULL_GROUP_BY)

例如(应根据第一步实际内容调整)

set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

然后再次查看sql_mode 如果目标参数已经不存在,尝试执行包含 group by 的sql,问题应该已经解决。

参考日志:
https://blog.csdn.net/qq_28867949/article/details/76850378