御用小编: 潘吉祥
说起来,宝宝的心里真的是难 ~~
本来作为一个大四的学生,此刻应该在一家像样的公司,做着一份像样的实习工作,为明年的毕业和就业作好前期工作。然而事实上是:一个出身卑微的本科院校,读着一个不太怎样的专业的业余学生党,一直到秋招结束,都碰壁在学校 。
于是乎只能继续学着层出不群的新技术,直到前几天,一个人在餐厅吃饭听到广播里的一连串的失物招领,我的脑子里就冒出一个想法:这样光是听声音没多少人能知道自己的东西是落在这里了,这样的话 ~~ (我从来不知道自己吃饭的时候是在想些什么东西,我的老天,我已经两个多月没和女孩子说过话了 / 瞪眼)
有了想法,那就立马开拔!十一月十号的中午,回到宿舍,从柜子底掏出我的机械键盘,开始大干一场。
首先是需求文档的编写,包括管理员和用户前端要实现的各种功能的抽象,还有就是用户界面的设计。当这些步骤从我脑海中升起的瞬间,我感觉自己成为了一名超级专业的工程师,有没有!!呃,事实上:
咳咳,那根据实际情况就一切从简了,然后就是根据需要的数据进行数据库的设计,当然也没有用 powerdesigner 这么高大上的专业工具(其实上手也是很容易的,有兴趣的伙伴可以自行学习使用。)
前期的工作大约花了整整一天半的时间,不过还是值得的。如果说从开始就上手编码,往往会有不少思路和设计上的停顿,磨刀不误砍柴工,说的就是这个道理呗。
先是后端整体框架的搭建( springboot+mybatisplus ),刚开始完全是按照这企业级别的规范来的,每个特定的功能分出一个单独的模块部署,而且各种负载均衡、 docker 、中间件、页面搜索静态化的想法还在脑子里层出不穷……
想也不用想,我可怜的戴尔刚起了三个工程外加一个 IDEA 应用,内存就被吃满了 / 捂脸,
从前,我以为以我的能力能够造航母,然后事实上,我的现实条件是连颗螺丝也拿不出来……
于是之前的分布式的工程全部推倒重来了,只起了一个 web 工程,承担所有的接口请求,顿时我感到一阵 ~ 疼,这下好了也不用什么负载均衡,什么集群了。
接下来是前端,虽说一直专攻的后端,但是前端现成的组件库也不错的,管理员后台用 elementUI+vue ,移动端是 vant+vue , 也能开发个看起来不是很丑的页面
虽然期间也遇到不少问题,例如页面的强制刷新、 TabBar 的状态停留,前后端通信的跨域、安全认证和前端的跨域问题……但是始终来说,技术问题只要理一理思路,动动脑子,总是能解决的。(这里就要做铺垫了 ~ )
就这样连续奋战十几个日夜之后,虽说还没有实现理想中的全部功能,但是当初出发点的功能已经能够完全使用了,跟伙管会展示了我的应用之后,他们说可以试试。于是我激动得开始要上线了,此前我已经进过大量测试,我自认为以学校的访问量是完全没有问题的 ~~
当然了,我肯定是没有买服务器,虽说学生价格挺优惠的,但是那个配置实在是不太行 (2G+ 单核 +1 兆 ) ,高配的还是要花大价钱,对于我这个连一份实习工作都没有的衰仔来说,实在是伤不起 emming.
于是乎,我首先想到的就是学校的公共——网,因为我在测试期间就是用这种方法的,只要连接学校的公网,就能访问服务器(学校有不少人都是办理了校园无线业务的)。话说回来,我不可能把自己的电脑作为服务器运行吧,那我还怎么开发。于是乎,我又跟室友借了一台笔记本 / 捂脸,(自从有了平板之后,他从来没动过他的电脑),配置还不错,在上面装了运行环境之后,就算部署上线了 ~
什么?域名?我穷得服务器都租不起,还去备案一个域名…… / 捂脸
听着笔记本 CUP 发出嗡嗡的运行声,哇,那声音简直是美妙,仿佛这天地的运行都是支撑在这台四核 8G 的笔记本电脑上!整个晚上都没有睡着。
第二天,后天管理系统被正式使用,我一改往日的衰废,去现场指导,更加重要的是使用者是一位小姐姐,她扎着乌黑顺直的翘高辫,干净白皙的脸庞竟稍有些害羞的红润,她说话的声音……咳咳,话题跑偏了,我是有公务在身的。
在我的引导下,她试着上传了几张电脑上的图片,添加上描述信息,再试着查看,删除……一切都再正常不过,完全在我的掌控之中。
可是就在我回到宿舍不到十分钟,就有电话打来:“是 xxx 学长吗?没法添加信息了呢 ~ ”
听到这句话的时候,我不知道自己在想什么,各位应该能想象到我的奔溃之情。
火速奔往事发现场,小姐姐立马给我演示,一模一样的步骤,点击添加之后,就是弹不出添加成功,打开开发者工具,居然服务器报错了,说是一个 bad 请求,鬼知道为什么是 bad 。无奈,既然出了问题,就只能想方设法解决,我又飞奔回宿舍,查看了 Tomcat 的错误日志,凭借我“老练”的经验,我一眼便看出了端倪: file size moer max-isze. 顿时我的脑海中想到了问题所在:
日常测试的时候大多数是从网上拷贝下来的图片,图片大小一般都不会很大,最多在 500KB ,因此从来没有出现过这个问题,而刚才管理员上传的图片时从手机拍照实物直接上传的,以现在手机的像素,最小也在一兆开外!
找到了问题的原因,现在有二种解决办法:
1 最直接的就是修改 Tomcat 的上传文件的最大大小,或者取消大小限制,但是这样带来的问题是,平均每一条记录就要占笔记本 2 兆多的硬盘,这怎么能承受呢, pass 掉。
2 把图片压缩:前端程序压缩、管理员人工压缩,理论上首先应该选择前端程序自己压缩,但是我之前完全没接触过这个,网上搜罗了资料,动不动几百行的封装 js 。为了尽快解决问题,就找了个图片压缩的软件装到了管理员的电脑上“以后上传前先把手机的照片用这个软件压缩一下,再上传就好了。”一顿操作,我又华丽地站在小姐姐跟前,问题 BUG 解决!
“果然唉!”
到这里,估计读者们也已经隐约感觉到些不妙的感觉了,下午的时候,管理员小姐姐又电话:“为什么我登录的用户不能上传头像呢?”
我的天,忘了用户前台和管理员前台用的一个 Tomcat ,虽然用户不需要上传大量图片,但是基本的头像修改还是要用的,还是面临了上传图片过大的问题。这总不能让每个用户上传个头像还要自己的手机上装个图片压缩文件吧。果然投机取巧的办法丝毫禁不起考验啊!
最后还是开始琢磨着前端上传压缩了,首先从管理员前端开始,找了不少资料,最后决定用了一个组件 image-conversion ,和 elementUI 结合比较简单:大概的用法是这样
首先导入 image-conversion 组件,然后就可以使用了
beforeUpload(file) {
return new Promise((resolve, reject) => {
let isLt1M = file.size / 1024 / 1024 < 1 // 判定图片大小是否小于 1MB
if (isLt1M) {
resolve(file)
}
// console.log(file) // 压缩到 200KB, 这里的 200 就是要压缩的大小 ,
imageConversion.compressAccurately(file, 200 ).then(res => { //
// console.log(res)
resolve(res)
})
})
},
beforeUpload(file) 方法是 elementUI 文件上传的一个方法,在这里对文件进行压缩,返回压缩的文件。
注意此时要不要让上传组件自动上传,要换成手动提交,才会向客户端传入压缩后的文件内容(深坑误入)。
: auto-upload =" false "
到此终于解决了“管理员”前端的图片压缩,为什么要强调“管理员”呢?
当我把相同的方法用于用户前端的时候,发现不能使用,在层层调试后发现:我的用户前端使用的是 vant ,而 vant 的图片上传会“贴心”地把图片文件转成 base64 编码,这一点倒是之前在做测试的时候就发现了,不过现在才又回想起来 ~
发现了问题,之前的图片转化组件就不能用了,又是一大堆搜罗,最后自己把压缩 js 简单地封了个方法组件,代码很简单,如下:
export function compressImg(file) {
// 创建 Canvas 对象 ( 画布 )
let canvas = document.createElement( 'canvas' )
// 获取对应的 CanvasRenderingContext2D 对象 ( 画笔 )
let context = canvas.getContext( '2d' )
// 创建新的图片对象
let img = new Image()
// 指定图片的 DataURL( 图片的 base64 编码数据 )
img.src = file.content
// 画布宽度
let width = 512
// 监听浏览器加载图片完成进行绘制
img.onload = () => {
// 画布大小按照图片的比例生成
let height = width / (img.naturalWidth / img.naturalHeight)
// 指定 canvas 画布大小,该大小为最后生成图片的大小
canvas.width = width
canvas.height = height
context.drawImage(img, 0 , 0 , canvas.width, canvas.height)
// 将绘制完成的图片重新转化为 base64 编码, file.file.type 为图片类型, 0.92 为默认压缩质量
// 返回压缩后的文件
return canvas.toDataURL(file.type, 0.92 )
}
}
在图片上传的 vue 组件中导入此方法,然后在上传组件的回调方法中执行:
afterRead(file) {
// 大于 1MB 的 jpeg 和 png 图片都缩小像素上传
if (file.file.size> 1000000 ) {
// 因为指定了只能上传一张图片,指定当前图片列表的 file 对象的 conten 为压缩后的 content 。
this .fileList[ 0 ].content = compressImg(file)
}
},
就此,大功告成!
为了个人信誉问题(其实还是迫于各种隐藏的 bug 的压力),还是把项目暂时下线了,此刻,我才体会到测试人员的作用真是举足轻重啊!还得自己好好测测……
在末尾,衷心祝愿各位同行能够远离 bug/ 捂脸。。。。
END
【推荐阅读 】
高级开发必须知道的分布式任务调度算法
阿里程序员的架构图是如何画的
程序员日常工作图鉴
7 个显著提升编码效率的 IntelliJ IDEA 必备插件
SpringBoot微信点餐开源系统
感谢阅读,请扫码关注
明天见