• 请不要在回答技术问题时复制粘贴 AI 生成的内容
frank1256
V2EX  ›  程序员

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

  •  
  •   frank1256 · Oct 9, 2022 · 7526 views
    This topic created in 1320 days ago, the information mentioned may be changed or developed.

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

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

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

    问下大佬们是这样的吗?

    Supplement 1  ·  Oct 9, 2022
    对方说 5MB ,妈耶代码里我发现日志打印了 request 的 body ,直接把文件给转 str ,跑了半天日志都没跑完。还是同步的日志。

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

    如果文件都是只有几百 KB 大小的,那还能凑合着用。要是文件是 MB 以上的体积,转 BASE64 纯属浪费资源
    zhangxh1023
        4
    zhangxh1023  
       Oct 9, 2022 via iPhone
    文件不大没关系,之前对接银行,他们的前置服务只能接受 json ,也是这么做的。又不是不能用.jpg🤓
    thinkershare
        5
    thinkershare  
       Oct 9, 2022
    你的接口 BODY 没有限制主体大小大小吗?如果有,直接编码为 Base64 没啥问题。不会有太大的问题。具体事情具体分析。
    wolfie
        6
    wolfie  
       Oct 9, 2022   ❤️ 1
    不修改老接口。
    新增一个 /v2/ 接口,form-data ,爱用不用。
    wbd31
        7
    wbd31  
       Oct 9, 2022
    nginx 可以限制 body 大小吧
    lmshl
        8
    lmshl  
       Oct 9, 2022
    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
    tf2
        9
    tf2  
       Oct 9, 2022   ❤️ 1
    multiple/form-data 记得把文件放在最后,否则别的字段你得把文件读完了才能处理。
    duke807
        10
    duke807  
       Oct 9, 2022
    用 msgpack 取代 json
    yousabuk
        11
    yousabuk  
       Oct 9, 2022 via iPhone
    bade64 后再压一下?
    dcsuibian
        12
    dcsuibian  
       Oct 9, 2022
    可以限制 http 大小的吧,比如:server.tomcat.max-http-post-size ?
    个人觉得小文件用 base64 上传其实没啥问题(比如头像),大文件还是用二进制,再大就还要考虑断点续传。看你实际情况。


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

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