V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
AquanllR
V2EX  ›  程序员

图片处理(海报生成 and 二维码生成),由前端处理还是后端处理好?

  •  1
     
  •   AquanllR ·
    sav7ng · 2021-02-08 10:18:55 +08:00 · 5662 次点击
    这是一个创建于 1382 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前端生成慢,后端生成样式难把控。 想看看大佬们的看法和建议

    56 条回复    2024-07-25 12:31:47 +08:00
    guoziq09
        1
    guoziq09  
       2021-02-08 10:26:44 +08:00
    我个人认为是前端,前端 1v1,后端 1vN 。
    bugmakerxs
        2
    bugmakerxs  
       2021-02-08 10:27:34 +08:00
    前端,后端生成过,日常低效接口 top10
    Symo
        3
    Symo  
       2021-02-08 10:28:00 +08:00   ❤️ 1
    反了吧, 前端生成样式才是比较难把控的. 用 html2canvas 转图片可能会遇到手机兼容性不好导致偏移的情况. 而且基本上没有办法发现.
    Orenoid
        4
    Orenoid  
       2021-02-08 10:30:24 +08:00
    前端生成可以把计算的压力分散到各个用户的设备上,但是少部分设备可能有兼容性问题,导致生成的图片样式不完全统一
    shyling
        5
    shyling  
       2021-02-08 10:31:15 +08:00
    对海报没啥概念,二维码应该是前端做更好点
    leeguo
        6
    leeguo  
       2021-02-08 10:31:59 +08:00
    才做过, 前端 有封装好的, 大小可调, 很方便
    Orenoid
        7
    Orenoid  
       2021-02-08 10:33:12 +08:00
    @Orenoid #4 除了生成图片的计算负载,后端生成可能还要上传 /下载图片,相对来讲也更费时间,个人倾向于前端生成。
    AquanllR
        8
    AquanllR  
    OP
       2021-02-08 10:35:54 +08:00
    @guoziq09 有道理,服务器生成得 1 对 N,不过后端可以做缓存处理
    AquanllR
        9
    AquanllR  
    OP
       2021-02-08 10:36:06 +08:00
    @bugmakerxs 建议前端吗?
    AquanllR
        10
    AquanllR  
    OP
       2021-02-08 10:37:20 +08:00
    @Orenoid 嗯,现在 2 个方案实现了,后端是要上传 oss,前端展示
    imgbed
        11
    imgbed  
       2021-02-08 10:44:09 +08:00 via Android
    前端的 canvas 已经很强大了,很多网页游戏都做得来,何况静态海报。写个专门的 js 作为海报生成专用吧
    bugmakerxs
        12
    bugmakerxs  
       2021-02-08 10:46:44 +08:00
    @AquanllR 是的
    sarices
        13
    sarices  
       2021-02-08 10:48:50 +08:00
    后端调用 Puppeteer 生成海报,缓存到 cdn
    maplerecall
        14
    maplerecall  
       2021-02-08 11:02:24 +08:00 via Android
    涉及文本的走后端,前端没法统一字体,除非对文字样式和排版要求不高。只是图片加二维码就走纯前端,图片不太多的情况下即使手机处理也非常快了。
    vevlins
        15
    vevlins  
       2021-02-08 11:04:15 +08:00
    前端,省省流量和内存吧,都是钱呀
    preach
        16
    preach  
       2021-02-08 11:05:08 +08:00
    看业务的量,过 10 万 uv 走前端
    kisshere
        17
    kisshere  
       2021-02-08 11:24:47 +08:00   ❤️ 1
    if($is_generated_poster_dynamically)
    {
    后端走起();
    }elseif($daily_pv>100000)
    {
    前端走起();
    }
    kisshere
        18
    kisshere  
       2021-02-08 11:26:30 +08:00
    @kisshere #17 第一个打错了,是前端走起
    TimPeake
        19
    TimPeake  
       2021-02-08 11:30:41 +08:00   ❤️ 1
    二维码可以前端弄,但是海报真的不好搞。有人说 canvas 已经很强大了 是,没错 ,但是相应的工具包 html2canvas bug 很多,唯一能用的也只有这个吧。
    weixiangzhe
        20
    weixiangzhe  
       2021-02-08 11:49:59 +08:00 via Android
    前端处理就好啦,全部 canvas 渲染
    throns
        21
    throns  
       2021-02-08 12:03:35 +08:00 via iPhone
    @TimPeake 做过类似的,html2canvas 问题挺多的,img 标签有问题,字体也有问题。最后还是通过调用 Puppeteer 来截图的,对了,还需要在服务器上安装字体,挺麻烦的,不过后面弄成 docker 镜像,部署还算方便
    AquanllR
        22
    AquanllR  
    OP
       2021-02-08 12:03:47 +08:00
    走的是阿里的 oss,估计后面会烧钱
    AquanllR
        23
    AquanllR  
    OP
       2021-02-08 12:04:26 +08:00
    @kisshere 是都走前端吗?
    wingoo
        24
    wingoo  
       2021-02-08 13:04:41 +08:00
    ali 的 oss 可以添加水印, 可以用这个功能生成海报
    killergun
        25
    killergun  
       2021-02-08 13:16:37 +08:00
    后端说前端好,前端说后端好
    markgor
        26
    markgor  
       2021-02-08 13:24:48 +08:00   ❤️ 4
    PC 端,html2canvas 浏览器不同内核版本 /html2canvas 不同版本都能蹦出一堆 BUG 。
    手机端,简单的 canvas 生成完成,但是不同品牌不同平台的小程序不一样的体验。

    最终:后端生成

    后来还涉及到原海报某些附带二维码,某些没有附带二维码,附带二维码的执行替换,没有附带二维码的对原图拉高插入二维码到底部....

    还好当初选择后端生成。

    当初想法和 1L 如出一辙。1V1 和 1VN 的区别,而且还省下带宽。可惜浏览器的差异化实在太恐怖了....现在后端生成性能其实还好吧,毕竟不需要每秒生成几十张,实际情况生成的并发量并不会太高,而且后端生成做做文件名缓存,防止重复生成即可了。
    markgor
        27
    markgor  
       2021-02-08 13:37:45 +08:00
    应该这样说吧,取决场景和业务;

    小程序前端,canvas 一直有问题,加载字体绘画更加别想了。
    H5 前端:canvas 支持不一,出来效果往往事与愿违。
    但是如果单纯图片缩放叠加拉伸----那样前端没多大问题,偶尔走走样总会有的。
    后台表单类的,导出 PDF/JPG 等,通过 canvas 的话 CSS 部分属性不支持,table 边框支持不完善....建议后端
    复杂多平台等业务下:建议后端生成。
    AquanllR
        28
    AquanllR  
    OP
       2021-02-08 13:42:19 +08:00
    @markgor Get!
    AquanllR
        29
    AquanllR  
    OP
       2021-02-08 13:43:44 +08:00
    前端小程序有一个开源库 https://github.com/Kujiale-Mobile/Painter 其实复杂的也可以操作
    markgor
        30
    markgor  
       2021-02-08 13:54:20 +08:00
    @AquanllR 我之前是用 uniapp 多端开发的,直接在插件市场找过 2 个,最终测试都不符合需求。
    你可以试试看使用开源库那里的,如果能符合你需求那就直接前端生成。
    markgor
        31
    markgor  
       2021-02-08 14:01:34 +08:00
    @AquanllR 哈哈哈,刚去 Painter 那看了,你进去 issues 那看看。然后幻想一下,每当出现(微信 CANVAS 渲染 BUG 或插件 BUG ),客户小姐姐一直 @你的场景。如果是微信 canvas 问题,你能做的只有等微信修复,还要弄一堆复现代码给微信。可是你能等业务不能等,小姐姐天天 @你,你能干的只有要么干掉小姐姐,要么干掉 canvas,要么被老板干掉
    u6pM63mMZ34z32cE
        32
    u6pM63mMZ34z32cE  
       2021-02-08 14:08:01 +08:00
    这得看谁的老大级别大, 像这种前后端都能做的需求, 一般都是级别小的人做
    AquanllR
        33
    AquanllR  
    OP
       2021-02-08 15:18:19 +08:00
    @markgor 这样考虑的话,可控性的话,还是后端好。
    Exia
        34
    Exia  
       2021-02-08 17:05:40 +08:00
    做过,都是前端生成的,不知道这海报有多复杂,可以看前端是否能搞定。
    stevenkang
        35
    stevenkang  
       2021-02-08 17:36:05 +08:00
    我在想,这图片后端处理的话,是消耗 GPU 资源吧?然而大多数后端服务器 GPU 都很弱。所以到底是前端生成慢,还是后端生成慢呢?
    freakJacker
        36
    freakJacker  
       2021-02-08 20:42:51 +08:00
    前端没办法统一,除非都是图片拼接。
    后端烧性能。
    这东西也不难,一般能前端做就前端做了
    DiamondYuan
        37
    DiamondYuan  
       2021-02-08 20:53:08 +08:00
    serverless 生成
    max1024
        38
    max1024  
       2021-02-08 21:01:35 +08:00
    前端生成不难吧。
    zqjnew
        39
    zqjnew  
       2021-02-08 21:19:06 +08:00 via Android
    二维码可以固定,然后跳的链接做动态代理,
    海报可以混合模式,即服务端做大块,前端做小块或整合
    OHyn
        40
    OHyn  
       2021-02-08 21:30:36 +08:00
    能接受效果不统一的,前端能做。
    Lemeng
        41
    Lemeng  
       2021-02-08 22:12:34 +08:00
    前端
    foxcell
        42
    foxcell  
       2021-02-09 08:18:43 +08:00
    前端
    没有必要的计算量还是扔给用户端分担
    markgor
        43
    markgor  
       2021-02-09 12:22:56 +08:00
    @AquanllR 后端结果统一且稳定,而且生成海报这个业务并发量也不大...
    @Exia 前端其实不可控因素太多,特别是多端环境下的开发...哪怕只是 H5,不同内核呈现出的效果都有一定差异。
    @stevenkang 想多了,后端处理基本都是跑 CPU 资源,占用的大户是 CPU>带宽>内存。

    其实结合上面所有的观点,都是建议 前端生成,理由是节省资源和带宽。

    这点我同意,但我也给我之前项目经验给你参考:

    业务 1:生成业务员名片,格式固定,获取头像、姓名、部门、二维码,复制到模板对应位置即可。
    方案:PC 前端生成名片
    坑:浏览器分辨率,浏览器缩放,屏幕大小(有些用 PC,有些用手机)
    处理结果:被人 @了 2 周,终于稳定了;其中缩放功能导致的异常没法解决,只能建议他们别缩放。

    业务 2:客户手机端产品海报生成,产品图为主图,背景为产品图+300 像素,左边放产品名称和推荐人头像姓名,又边放产品链接二维码;
    方案 1:前端生成
    坑:产品名称过长,昵称含有特殊字符的,直接 GG 了,多端( h5,微信小程序,抖音小程序)展示的效果不一致,其中印象最深的是微信小程序 IPHONE7 机型,完全走样。基本功能上线后天天被人 @ 。

    方案 2:后端生成
    坑:由于后续海报图增加了价格显示,但是产品价格会改变,当初做缓存的时候没考虑到这个因素,导致某天突然被 @说海报的价格不一致......。
    处理结果:把用户昵称 + 产品 ID + 产品价格 做个 MD5,请求是判断是否存在,存在就直接返回,不存在就走生成逻辑。
    ---至今稳定,也没出现 CPU 毛刺之类,后续还加入了 QRCODE 查找替换的功能....
    后来也有过小坑,带宽偶尔出现毛刺,查监控找不到规律。
    某来突然发现是用户下载海报时候导致的。因为部分图片大小逼近 4~5MB 。(产品主图有做 CDN 缓存,但是生成的海报没做缓存)
    解决方法:用户->CDN->COS->源;



    结合上面自身案例,结论:
    后端生成
    优点:稳定,生成结果统一、后期海报需求变复杂的情况下也能支撑。
    缺点是:
    1 、原图过大的话海报会影响带宽----通过 CDN 解决
    2 、防止 CPU 瞬间飙升---通过判断文件是否已经生成(缓存),要求再高的话可以单独一个服务出来。


    前端生成
    优点:节省计算资源、带宽;
    缺点:不同终端不同内核结果不一,无法支撑复杂业务;



    BTW:
    如果你把标题改为 “后端处理海报 AND 二维码 的能力 和前端处理的能力对比”,估计你会得到不一样的结果。
    zuiye111
        44
    zuiye111  
       2021-02-09 15:21:16 +08:00   ❤️ 1
    正好最近在做一个海报中心项目,当时做方案时也是在考虑前端生成还是后端生成,所以这个问题我也回答下
    我们的产品形态是小程序
    1 、前端生成
    优点:对后台友好,由于我们项目后台都是 C++,要找一个画图的库还是比较麻烦,前端合成可以降低后端开发压力,其次可以充分利用客户端计算性能,灵活
    缺点:就像上面说的,需要考虑不同机型适配,字体问题,其次,要考虑前端生成的海报如何传给后台?传二进制流?还是合成后上传 CDN 再给后台?再者,由于我们还支持用户上传图片,小程序里可能支持性不够好
    2 、后台合成
    优点:可控性,可靠性,统一性更好
    缺点:开发成本较高
    最终和前端同事讨论比较,还是选择后台单独写个合成图片的服务,前端使用 svg 渲染海报模板,用户编辑后,再把 svg 转 json 传给后台,后台合成图片并上传 cdn,返回给前端 cdn 地址,最终,经过优化,合成的速度基本控制在 1~2s 。
    目前我们海报中心小程序已经在灰度中,支持特殊字体,好友码,上传图片等功能,如下图
    https://wx.gtimg.com/resource/feuploader/202102/b540d53198dd75d1b2c2d9cad6453014_1080x2337.jpg
    sujin190
        45
    sujin190  
       2021-02-09 18:18:49 +08:00 via Android
    @stevenkang 后端 2d 绘图,cpu 绘制的吧,而且现在用的比较多的云主机似乎没有 gpu 的吧
    AquanllR
        46
    AquanllR  
    OP
       2021-02-20 12:00:16 +08:00
    @markgor 感谢耐心的解答
    AquanllR
        47
    AquanllR  
    OP
       2021-02-20 12:00:45 +08:00
    @DiamondYuan 是个不错的方案,纳入考虑范围
    AquanllR
        48
    AquanllR  
    OP
       2021-02-20 13:43:59 +08:00
    @markgor 有一个疑问就是业务 2 的方案 2,会出现一种场景就是,产品名称参数修改了,海报上面的标题因为已经存在了,不会重新生成,而导致海报上的数据是旧的问题。
    感觉得商品编辑修改的时候同步去修改
    markgor
        49
    markgor  
       2021-02-20 14:28:39 +08:00
    @AquanllR
    >产品名称参数修改了,海报上面的标题因为已经存在了,不会重新生成,而导致海报上的数据是旧的问题。
    前端传:价格-产品标题-产品图片 url-openID(userID)-用户名称
    后端:根据上面的信息,组合字符串,在走个 MD5,出来的结果就能保证一致了。

    >感觉得商品编辑修改的时候同步去修改
    应该不可以吧,看你业务海报图是否需要用户信息。
    如果不需要用户信息可以。
    如果需要用户信息那你触发的地方只有用户点击生成后吧?
    markgor
        50
    markgor  
       2021-02-20 14:34:47 +08:00
    @AquanllR
    前端:POST->price 、title 、posterUrl 、openID 、nickName
    后端:
    //简单:
    $FILENAME = MD5($title . $posterUrl . $price . $openID . $nickName);
    //复杂:(感觉没必要)
    $FILENAME = MD5(md5($title) . md5($posterUrl) . md5($price) . md5($openID) . MD5($nickName));

    //判断海报是否已经生成:
    $FILENAME .= '.jpg';

    if(is_file($_PATH_TO_DIR . $FILENAME)){
    //存在:输出
    }

    //不存在:进入生成流程





    --------------
    不知道怎么表达,文字功底薄弱,
    中心思想就是把影响生成的条件(变量)并在一起,生成个 MD5,然后判断文件是否已经生成。
    AquanllR
        51
    AquanllR  
    OP
       2021-02-20 16:05:26 +08:00
    @markgor 十分感谢!现在问题已经很明朗了~再次感谢
    AquanllR
        52
    AquanllR  
    OP
       2021-02-20 16:05:45 +08:00
    感谢大家的热情讨论!
    xmsz
        53
    xmsz  
       2023-02-09 12:08:12 +08:00
    综合 我认为应该是后端...

    如果直说浪费后端资源 /客户端 1v1 的,那应该没做过,或者天真一点的,或者海报就很简单,或者是完全不追求生成效果,或者完全不管用户反馈的场景...


    前端生成的问题就是
    1. 复杂海报每次生成需要时间,是每次,用户用一次生成一次。体验并不好,除非你生成后再放到 CDN 上(那还不如...)。我们之前开发的头像小程序就是,蛮尴尬的...
    2. 遇到字体文件,吐血... 你总不能给客户端下载个 10m 的字体?
    3. 最恶心的来了,你这个服务只能兼容 90%左右的情况,而剩下 10%会搞死你
    ...

    特别是最后一点,就算你兼容的是 99%,那 1%还是会搞死你。
    一般的人根本不懂兼容,他只觉得没能兼容 100%就是你的问题,你直接气疯...
    而且我们公司有个后端程序员居然也怎么想... 真的尴尬


    对于后端来说,只需要考虑『资源』问题
    对于产品、设计、前端来说,要考虑的不仅仅是『资源』,还要『兼容』、『效果』、『体验』....

    所以综合起来肯定是后端生成


    当然,如果其他前端好的方案也可以讨论
    我们 web 端和小程序,基本已经穷尽了,当然自己也用 canvas 写了,但效果真的...
    AquanllR
        54
    AquanllR  
    OP
       2023-02-09 14:58:36 +08:00
    我们开始是先使用了前端生成的,最后最终方案走的是后端生成方案进行了
    @xmsz
    lizy0329
        55
    lizy0329  
       119 天前
    1 Dom -> image ( IOS 兼容性很差)
    2 Dom -> base64 ( html2canvas 有很多 BUG )
    3 Dom -> svg -> base64 -> 七牛返回 png 等 image

    3 这样可行?
    lizy0329
        56
    lizy0329  
       119 天前
    @zuiye111 yes
    SVG to Image 在后端进行,可用性是最棒的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1303 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:38 · PVG 07:38 · LAX 15:38 · JFK 18:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.