做了个网页版 PDF 压缩工具,解决「不想上传隐私文件」的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
hiko2chen
V2EX    分享创造

做了个网页版 PDF 压缩工具,解决「不想上传隐私文件」的问题

  •  
  •   hiko2chen 9 天前 3139 次点击

    起因是有一个银行的亲戚,需要压缩一个用户的合同 PDF ,内容基本拍摄的合同照片导致文件很大,因为文件敏感涉及到具体客户信息,所以不想使用需要上传文件的在线服务,私聊让我帮他手动压缩一下。 弄完后我发现对于一些,可能企业内部没有提供工具,但是又有敏感文件压缩的人来说,当前确实希望有一个即时可用,安全的工具。

    所以就做了这个: 打开网页就能用,无需下载安装 文件在浏览器里处理( Ghostscript WASM ) 完全不上传服务器

    技术栈:React + Ghostscript WASM + Cloudflare Pages

    适合场景:偶尔压缩几个 PDF ,注重隐私,即时可用 不适合:批量处理或需要高级功能

    域名是 https://safetypdf.com

    上线以后没怎么做推广,不过也有 19 个自然流量用户压缩了文件,节省 362MB 空间。 欢迎 v 友们试用,有问题随时提~

    50 条回复    2025-11-07 20:01:29 +08:00
    cowcomic
        1
    cowcomic  
       9 天前
    点赞
    shortawn
        2
    shortawn  
       9 天前
    你的亲戚私聊让你帮他手动压缩一下,是怎么私聊的,微信吗?(狗头)
    xinyu391
        3
    xinyu391  
       9 天前
    确实离线操作的,
    wasm ,大概率用的 pdfium
    xinyu391
        4
    xinyu391  
       9 天前
    @xinyu391 没看全文章,原来是 GhostScript 。
    但 GS 是 AGPL 和商业授权,
    题主,如果不公开整个网站源码,那就是要花钱买授权了。
    catazshadow
        5
    catazshadow  
       9 天前   1
    windows 上的 xodo 可以压缩
    PbCopy111
        6
    PbCopy111  
       9 天前
    WPS 就有 PDF 压缩工具,本机的,250M 的文件,最小压缩到 3M ,还能选择各种画质,实属国企最爱。
    hiko2chen
    &nbs;   7
    hiko2chen  
    OP
       9 天前
    @xinyu391 是的,感谢提醒,我之前也注意到了 GS 的 AGPL 协议,这两天在测试使用 pyodide 实现一些 MIT 库的 wasm 化来实现相同功能,当前实现了一个 pikepdf 的,不过测试压缩性能和文件兼容能力对比 GS 差太大多了

    如果这周还没解决,我就会把当前网站全部开源了,不过本身也是免费的~
    hiko2chen
        8
    hiko2chen  
    OP
       9 天前
    @cowcomic 感谢~
    hiko2chen
        9
    hiko2chen  
    OP
       9 天前
    @shortawn 是的,不过我亲戚估计也不会想到微信会不会偷看哈哈哈
    hiko2chen
        10
    hiko2chen  
    OP
       9 天前
    @catazshadow 确实不错,但是我估摸着他没听说过哈哈
    hiko2chen
        11
    hiko2chen  
    OP
       9 天前
    @PbCopy111 是的,WPS 我感觉啥功能都有,不过好多都要付费,下次有其他需求我让他自己买个 WPS 最好哈哈哈
    EeveeRibbon
        12
    EeveeRibbon  
       9 天前
    但是我发现,用户视角上这个还是一个浏览器,需要"上传"到网页上,绝大多数用户不了解浏览器是可以本地处理的
    hiko2chen
        13
    hiko2chen  
    OP
       9 天前
    @EeveeRibbon 对的,我理解你说的!大多数普通用户对于浏览器还是会有固有印象,是一个联网的东西,本地感知这点肯定比不上一个下载安装的 App 。
    我当前的解决方案也是在 UI 上加入了一些文案来说明“本地”性质,当前还是先强化即时可用这个

    后续有灵感和精力了,我在考虑从交互流程上去优化它,效果应该会更好~
    yechentide
        14
    yechentide  
       9 天前 via iPhone   1
    参考 ios ,让用户选择“给予访问权限的文件”,而不是让用户“上传文件”,或者弄成 PWA
    acherkrau
        15
    acherkrau  
       9 天前
    尝试了压一个 50 页纯文本的 pdf, 速度很慢, 压缩率倒是挺高的
    hiko2chen
        16
    hiko2chen  
    OP
       9 天前
    @acherkrau 是的,Ghostscript 原生的性能非常不错,不过 wasm 化后,可能只有 20% 不到的性能,用来换取即开即用的便利了
    hiko2chen
        17
    hiko2chen  
    OP
       9 天前
    @yechentide 感谢建议,文案方向很有用!
    关于 PWA ,其实当前是支持的,但不是完全体,有 webmaifest 文件,chrome 会提示安装,不过没有实现 Service Worker ,因为后续可能会更新引擎,所以暂时不做缓存处理,等到完全体后再考虑更新
    ImmerTry
        18
    ImmerTry  
       9 天前
    有意思的创意,感谢分享
    kfpenn
        19
    kfpenn  
       9 天前
    这个网站完成度好高啊,要是我做一个小工具可能就一个主页功能区,不得不赞叹 OP 的执行力
    docx
        20
    docx  
       9 天前 via iPhone
    银行电脑能随便访问外网?
    Charon2050
        21
    Charon2050  
       9 天前
    好漂亮的网站虽然我不需要处理 PDF ,但还是收藏了。太漂亮了
    9RWBdC758updU311
        22
    9RWBdC758updU311  
       9 天前
    首先开源吧
    37Y37
        23
    37Y37  
       9 天前   1
    这个不错,我也挺喜欢浏览器本地处理的,还做了一系列浏览器本地图片处理工具 https://img.ops-coffee.com/tools/ 现在 AI 太方便了,疯狂造轮子
    Ccf
        24
    Ccf  
       8 天前
    看起来不错
    enrolls
        25
    enrolls  
       8 天前
    @hiko2chen 提供一个 exe 呗~,可能懂技术的人就选择 PWA
    abc8678
        26
    abc8678  
       8 天前 via Android
    @enrolls 陆陆续续替换成麒麟或统信了
    abc8678
        27
    abc8678  
       8 天前 via Android
    @hiko2chen 请问支持保存网页后拷贝吗?内网场景
    gdfsjunjun
        28
    gdfsjunjun  
       8 天前
    @PbCopy111 试了下,WPS 要会员,收费啊!
    gdfsjunjun
        29
    gdfsjunjun  
       8 天前
    不知道哪里出了问题,反向压缩啊?

    penisulaS
        30
    penisulaS  
       8 天前
    需要假装成一个 app 才好
    xinyu391
        31
    xinyu391  
       8 天前
    @PbCopy111 动不动就会员收费。昨晚打印一个大文件,打印机嫌太大,想找 wps 拆分,也要收费。。。
    kukuCode
        32
    kukuCode  
       8 天前
    大佬,请问你这是哪家的服务器呀,年费多少?
    hiko2chen
        33
    hiko2chen  
    OP
       8 天前
    @enrolls 后续有空了打包一个~

    @abc8678 暂时还不支持直接直接保存离线使用,因为当前没有 Service Worker ,wasm 文件每次是动态获取的,只支持弱网使用,后续会推进 PWA 这块

    @gdfsjunjun 这个有点尴尬,你的 PDF 是不是本身已经被其他工具压缩过啦?之前遇到过类似的问题是这个情况,或者你的文件内容是什么类型的呀,都是图片或者文字?
    hiko2chen
        34
    hiko2chen  
    OP
       8 天前
    @kukuCode 挂在 cloudflare 的 pages 上面的,免费请求额度非常多,个人完全够用
    elboble
        35
    elboble  
       8 天前
    以前 docker 部署了 Stirling PDF ,常用的功能也就是压缩 pdf ,上传还慢。等开源学习下
    gdfsjunjun
        36
    gdfsjunjun  
       8 天前   1
    从云原生到 AI 原生核心技术 & 最佳实践.pdf
    从阿里云开发者社区下载的,原地址找不到了,文件内容是 PPT 转 PDF 的

    找了个临时快传

    https://www.filemail.com/d/dpwejkwvpqhrcrx

    你可以自己测试下
    dimwoodxi27
        37
    dimwoodxi27  
       8 天前
    试用发现和外网大部分的 PDF 压缩网站效果一致,从质量和压缩体积来看都没 Adobe Acrobat 好; wasm 十几 M ,也太臃肿了吧
    hiko2chen
        38
    hiko2chen  
    OP
       8 天前
    @gdfsjunjun 感谢,我本地测试一下

    @dimwoodxi27 是的,有很多更好的解决方案,当前产品主要是为了解决即时可用和无需上传,保护隐私两个需求方向,所以会有一些取舍
    wasm 目前还使用的是 GS 原版,很难自行编译精简,也是目前在考虑更新换轻量库
    Izual_Yang
        39
    Izual_Yang  
       8 天前
    用的 gs 参数是什么?我自己平常用的 gs 命令行压缩参数偏保守,我用手头上的图文 pdf (非扫描)测试:
    原 PDF 98.3 MB ,
    SafetyPDF 64.2 MB ,
    自己的 gs 命令行 75.4 MB ,
    pdfcpu 82.6 MB ,
    qpdf 只能减少 1-2MB
    Izual_Yang
        40
    Izual_Yang  
       8 天前
    @kzfile #30
    套一层 electron 或者 tauri 是吧
    Izual_Yang
        41
    Izual_Yang  
       8 天前
    @Izual_Yang #39 看了一下就是 /screen 和 /printer ,那确实快
    dimwoodxi27
        42
    dimwoodxi27  
       8 天前
    @hiko2chen 按加载体感来说感觉慢,而且其他的 PDF 压缩网站加载更快,但感觉你这个压缩速度还行是我用过十几个 PDF 中算最快的,其他的都是上传到后端压缩的,但你这个算是离线压缩是不错的方式,网站体积和质量压缩更小是能比 90%的 PDF 压缩网站好用的;个人感觉大部分人压缩 PDF 的目的就是为了上传到一些在线文档,而在线文档限制了 PDF 的上传体积为 100M 以内。
    hugodotlau
        43
    hugodotlau  
       8 天前
    @Izual_Yang 不太理解 SafetyPDF 和 gs 命令行不应该一致么?
    hugodotlau
        44
    hugodotlau  
       8 天前
    果然是 gs , 小文件负压缩效果问题还存在 :D

    原始大小
    5.44 MB
    压缩后大小
    5.66 MB
    节省空间
    -4.2%
    hiko2chen
        45
    hiko2chen  
    OP
       8 天前
    @gdfsjunjun 我找到问题了
    [核心原因]
    1. 原 PDF 里面的 JPEG 文件已经经过一次压缩率较高的“激进压缩”,文件已经很小且优化了。
    2. 如果使用的是推荐模式进行压缩的话,我的 GS 内使用的是/printer 预设进行压缩,内部的参数 QFactor 较低,相当于保守压缩,此时 GS 会对 JEPG 全部解码重新编码。
    3. 因为重新编码参数更保守,所以会尝试保留更多已经在第一次压缩时丢失的细节,编码一些已经损坏的数据。

    最终导致体积上升。

    而且我算了一下,这个文件 280 个 JPEG 图片,使用重压缩,每个图片可能会增加 50-100KB ,增量也是差不多 21 MB ,和预期差不多

    [解决方案]
    对于这种已经被压缩处理过的 PDF ,再压缩的方式可以使用极致压缩模式,这样会再对内容进行有损压缩,但是速度会较慢,我试了下,压缩了 18%,从 51MB 压缩到 42MB 。
    不过我当前这个也有设计缺陷,我后续考虑拓展一下 PDF 分析组件,提前提取分析 jpeg 质量,如果高于当前压缩算法,忽略重新编码 jpeg ,仅优化数据流
    hiko2chen
        46
    hiko2chen  
    OP
       8 天前
    @dimwoodxi27 主要还是有些文件,比如比较重要的合同,文件,私人的内容之类的,上传到别人服务器总是有些不放心
    hiko2chen
        47
    hiko2chen  
    OP
       8 天前
    @hugodotlau 这个问题不知道是不是也是类似上面的,小文件里面的图片文件已经被压缩过了,推荐模式的重新编码可能会导致体积上升
    hugodotlau
        48
    hugodotlau  
       6 天前
    @hiko2chen 不完全是,理论上你可以先提取图片判断压缩率后,再决定压缩策略。这里面有个更难的问题是重新生成的 pdf 的字库会被更新有可能变大
    PbCopy111
        49
    PbCopy111  
       5 天前
    @xinyu391
    @gdfsjunjun 国企最爱啊,国企付费使用没毛病吧。
    wxf666
        50
    wxf666  
       4 天前
    @hiko2chen #45

    36 楼的 PDF ,可能重复图片只保存了一份,但你可能重复压缩并存储了,所以体积缩小不明显?

    ---

    1. 我用 pdfimages 解包出原始图片,压缩前共 55.6 MB ,极致压缩后共 21.0 MB ,都是 6297 张。

    2. 再用 rdfind 删除重复文件后,压缩前剩 3086 张 27.4 MB ,极致压缩后剩 3186 张 9.2 MB 。(难道同一张图片,多次压缩结果不同?)

    3. 猜测:

    3.1 原 PDF 只存储一份重复图片(因为 55.6 MB > 51 MB ,还有其他内容、字体等要存储)

    3.2 极致压缩后,可能重复图片也原样存储了,因为 ( 51 MB - 42 MB = 9 MB 极致压缩后节省体积 ) = ( 27.4 MB - 21.0 MB + 其他被精简掉的 2.6 MB ),看起来对得上?

    3.3 如果极致压缩后,也能去掉重复图片,最终文件应该能小至 30 MB ?


    ---


    感觉除非大幅牺牲画质,jpg / png 已经很难再减少体积了。。

    要是 PDF 支持 avif 、heic 、jpeg-xl 等先进格式图片,就好了。。

    4K 阿凡达图,4.23 MB jpg ,压成0.15 MB avif ,减少 97% 体积,细节纹路噪点都还保留的可以。。

    实测 avif-enc 压一遍那 3086 张原图,原始分辨率,画质基本不变时,可减少 72% 体积,只剩 7.8 MB 。。

    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3111 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 11:33 PVG 19:33 LAX 03:33 JFK 06:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86