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

如果文件直接用 base64 编码传,会怎么样

  •  
  •   frank1256 · 2022-10-09 17:21:30 +08:00 · 6665 次点击
    这是一个创建于 755 天前的主题,其中的信息可能已经有所发展或是发生改变。

    修改一个上传文件的接口给同事,本能的就使用 form-data 。 原本是没有上传文件的需求,content-type 是 json ,现在我改成 form ,分 2 个 key ,一个是 attachments ,一个是 req ,req 是原来 json 的字符串。

    同事说直接让我还用 json ,并且在它直接将文件转 base64. 跟图片一样的意思。

    他说附件不大,我觉得这样有隐患,该怎么说呢,我认为我毕竟是接口,万一给我传个 500M 的字符串啥的,这 500M 我不就全部要吃到内存里。而通过 multiple/form-data 的话,应该是从 io 流里读的,不会一次性吃 500M 内存。

    问下大佬们是这样的吗?

    第 1 条附言  ·  2022-10-09 19:05:46 +08:00
    对方说 5MB ,妈耶代码里我发现日志打印了 request 的 body ,直接把文件给转 str ,跑了半天日志都没跑完。还是同步的日志。

    他那边编码 base64 ,我再解码,纯纯的浪费时间
    36 条回复    2022-10-11 14:52:40 +08:00
    crab
        1
    crab  
       2022-10-09 17:33:56 +08:00
    主要区别不是直接支持二进制不需要编码增大文件吗,如果是大文件不切片也会遇到这情况啊。
    Pastsong
        2
    Pastsong  
       2022-10-09 17:36:46 +08:00
    你传 500M 的字符串你也可以从 io 流里读,看具体实现
    问题在于编码解码的损耗,文件体积膨胀,和你的编码解码器可能不支持流式处理。
    eason1874
        3
    eason1874  
       2022-10-09 17:39:10 +08:00
    脱裤子放屁,客户端转码要花时间,服务器转码要花时间,还增加 30%体积浪费流量

    如果文件都是只有几百 KB 大小的,那还能凑合着用。要是文件是 MB 以上的体积,转 BASE64 纯属浪费资源
    zhangxh1023
        4
    zhangxh1023  
       2022-10-09 17:40:04 +08:00 via iPhone
    文件不大没关系,之前对接银行,他们的前置服务只能接受 json ,也是这么做的。又不是不能用.jpg🤓
    thinkershare
        5
    thinkershare  
       2022-10-09 17:42:15 +08:00
    你的接口 BODY 没有限制主体大小大小吗?如果有,直接编码为 Base64 没啥问题。不会有太大的问题。具体事情具体分析。
    wolfie
        6
    wolfie  
       2022-10-09 17:42:24 +08:00   ❤️ 1
    不修改老接口。
    新增一个 /v2/ 接口,form-data ,爱用不用。
    wbd31
        7
    wbd31  
       2022-10-09 17:53:56 +08:00
    nginx 可以限制 body 大小吧
    lmshl
        8
    lmshl  
       2022-10-09 18:02:46 +08:00
    form-data 里的文件可都是暂存文件系统的,你不主动调用不会全部读进内存。
    但一个 JSON 字符串大概率你很难做流式解析(很复杂),严格解析完了可就全在内存里了。

    参考:
    The file contents are either stored in memory or temporarily on disk. In either case, the user is responsible for copying file contents to a session-level or persistent store as and if desired. The temporary storage will be cleared at the end of request processing.
    https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html
    lambdaq
        9
    lambdaq  
       2022-10-09 18:23:08 +08:00   ❤️ 1
    multiple/form-data 记得把文件放在最后,否则别的字段你得把文件读完了才能处理。
    duke807
        10
    duke807  
       2022-10-09 18:31:56 +08:00
    用 msgpack 取代 json
    yousabuk
        11
    yousabuk  
       2022-10-09 18:38:54 +08:00 via iPhone
    bade64 后再压一下?
    dcsuibian
        12
    dcsuibian  
       2022-10-09 18:39:29 +08:00
    可以限制 http 大小的吧,比如:server.tomcat.max-http-post-size ?
    个人觉得小文件用 base64 上传其实没啥问题(比如头像),大文件还是用二进制,再大就还要考虑断点续传。看你实际情况。


    体积、流量问题我觉得见仁见智,有些人连字段长度都要省,base64 简直罪无可赦:
    https://www.v2ex.com/t/868167
    wangritian
        13
    wangritian  
       2022-10-09 19:51:54 +08:00
    不理解,传 multiple/form-data 要浪费他几天时间吗?
    adoal
        14
    adoal  
       2022-10-09 20:10:18 +08:00
    要不,开个 webscoket 吧
    ufan0
        15
    ufan0  
       2022-10-09 21:27:12 +08:00
    @wangritian #13 就用这楼的话回复他吧

    我就遇过对接方这么干,N KB 就忍了,后面传 N MB 的的过来,网关直接拦截,他们自己的业务全面受阻,呵呵~
    xuanbg
        16
    xuanbg  
       2022-10-09 21:35:12 +08:00
    不怎么样,就是体积变大而已。邮件的附件就是 base64 编码的。
    nkidgm
        17
    nkidgm  
       2022-10-09 23:42:53 +08:00
    浪费带宽。
    zhuweiyou
        18
    zhuweiyou  
       2022-10-10 00:00:44 +08:00   ❤️ 3
    有没有一种可能, 你同事不会.
    kkeep
        19
    kkeep  
       2022-10-10 00:36:06 +08:00 via Android
    网络就是被这种垃圾程序占用的😅😅😅
    baobao1270
        20
    baobao1270  
       2022-10-10 01:46:51 +08:00
    我觉得可以直接 restrul put 吧,body 直接就是文件内容,json 和文件分成两个接口
    binux
        21
    binux  
       2022-10-10 01:55:41 +08:00 via Android
    你又不是后端,他爆内存和你有什么关系?
    如果和你有关系,你帮他改成 form 不就完了。
    如果和你没有关系,你凭什么指手画脚?
    dangyuluo
        22
    dangyuluo  
       2022-10-10 05:30:14 +08:00
    你想一下,原本一个字节可以表示 0-255 这 256 种不同的数据,用 base64 编码之后,一个字节就只能有 65 种可能了,纯属是浪费时间空间
    hb751968840
        23
    hb751968840  
       2022-10-10 08:29:43 +08:00
    上传就是 form-data ,或者 PUT ,其他都是乱搞
    zilongzixue
        24
    zilongzixue  
       2022-10-10 08:42:36 +08:00
    这不是扯淡吗,改成 form-data 又不难,一个注解就完事了
    echo1937
        25
    echo1937  
       2022-10-10 08:50:47 +08:00
    当然可以啊,以前有个 Markdown 的编辑器,你粘贴图片的时候,他就是把图片转码成 Base64 附在 Markdown 文件的末尾。
    lcy630409
        26
    lcy630409  
       2022-10-10 08:59:04 +08:00   ❤️ 1
    一般有一个专门上传文件的接口和函数,原 json 参数传文件名即可,接口内 代码使用文件函数 转移文件到最终存放地,临时文件夹 定期清空
    lakehylia
        27
    lakehylia  
       2022-10-10 09:09:58 +08:00
    文件太大还是改接口吧,搞个 v2 接口
    Songxwn
        28
    Songxwn  
       2022-10-10 09:11:05 +08:00
    企业微信的微盘就是,第三方只能用 base64 上传
    DinnyXu
        29
    DinnyXu  
       2022-10-10 09:21:12 +08:00
    现在不都是用 url 后台解析吗? 前台将文件上传到 OSS 获得 url ,传输给后台一个 url ,后台自己解析 url 内容不就可以了吗,这不更快?
    nothingistrue
        30
    nothingistrue  
       2022-10-10 09:23:29 +08:00
    如果单看编程,base64 编码进 json 里面,省事的不光前端,也有后端,而且后端省事的更多。这个的问题是,随着文件的增大,接口的处理时间、服务器的并发能能力、网关、日志等多处地方的性能都会收到影响,而且通常影响程度至少是指数级。这东西是要在编程省事和性能优化之间做权衡的,做这个权衡的,应该是架构师或者有过经验的人,不是是当事开发前后端双方。
    seth19960929
        31
    seth19960929  
       2022-10-10 10:33:07 +08:00
    好的做法就是你前端直传文件就可以, 然后把文件 URL 和你 req 提交给后端
    unco020511
        32
    unco020511  
       2022-10-11 10:17:50 +08:00
    你们没有业务无关的存储服务吗,业务接口一般都不关注文件存储的,只关心 url
    MineDog
        33
    MineDog  
       2022-10-11 10:22:56 +08:00
    @dangyuluo #22 是这么算的?
    dangyuluo
        34
    dangyuluo  
       2022-10-11 14:30:20 +08:00
    @MineDog 如果是错误的话,请教正确的计算
    MineDog
        35
    MineDog  
       2022-10-11 14:47:35 +08:00
    @dangyuluo #34 我的问题,确实是浪费了 2bit 的空间
    MineDog
        36
    MineDog  
       2022-10-11 14:52:40 +08:00
    @dangyuluo #34 不过计算方式是原本 3*8=24bit 的数据需要 4*6(base64 字符,只表示 6bit 但实际还是占用还是 8bit )表示,相当于浪费了 2bit 的空间
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   942 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:32 · PVG 04:32 · LAX 13:32 · JFK 16:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.