HTTP 请求实现文件上传的问题,请教如何解决? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
lazyczx

HTTP 请求实现文件上传的问题,请教如何解决?

  •  
  •   lazyczx 2024 年 3 月 21 日 2102 次点击
    这是一个创建于 761 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想实现一个 Web 文件管理应用,刚刚用 SpringBoot 搭建了一个 Demo:

    public class FileController { FileService fileService; @PostMapping("/upload") public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file) { if (fileService.trySave(file)) { return ResponseEntity.ok("File uploaded successfully"); } return ResponseEntity.internalServerError().body("Failed to upload the file"); } } 

    ( Service 的代码就不放了,因为对于问题来说不重要)

    然后测试了一下接口,我把 url 打错了,然后上传了一个比较大的文件,结果请求了很久才返回 404 的 response 。

    然后我又试了以下,并且在期间打开任务管理器,发现 jdk binary 的磁盘 IO 高起来了。。等了半天,大约是文件传完了(或者说 HTTP 请求体传完了)才返回 resp 。

    然后我问 GPT 为什么会这样,它说因为我用 HTTP 请求传文件,服务端就是要接受了整个请求体(包含大文件)之后,才会处理 url 匹配之类的逻辑。我越想越离谱,这不是意味着我可以往接受大文件上传的域名一直发文件吗?然后每个被我请求的服务器都要进行磁盘 IO ,就因为这个 HTTP 协议的特性?

    然后我问了 GPT 解决方法,它给出

    • 用客户端做可达性分析

      似乎脱离了讨论的范畴,因为我直接测的接口,想知道在这个前提下的解决办法是什么

    • 用中间件验证权限和 url

      中间件也是服务器,也需要接受 HTTP 请求,那不也浪费了资源吗?

    • 用分片上传

      似乎还是无法避免浪费资源

    好像这些办法都没用,因为大前提都是使用了 HTTP 请求,因此服务器必须要接受这个请求之后再处理。。因此我看不出这些方法解决这个问题的可行性。

    渴望有人指点下我的迷惑。

    13 条回复    2024-03-22 11:40:41 +08:00
    tool2d
        1
    tool2d  
       2024 年 3 月 21 日
    和 gpt 说,用 ajax 来上传文件,可以控制上传进度。

    纯 http 上传相对来说,要复杂一点。
    githmb
        2
    githmb  
       2024 年 3 月 21 日
    不太可能额,我之前遇到这种情况是多了一层傻逼的防火墙
    服务器拿到请求第一行就能拿 URL 去做匹配了呀
    POST /upload HTTP/1.1
    Host: xxx
    em998
        3
    em998  
       2024 年 3 月 21 日
    用云存储服务, 从客户端直接传到云平台
    momo1999
        4
    momo1999  
       2024 年 3 月 21 日
    java 不懂,nginx 有 client_max_body_size ,应该类似吧
    tool2d
        5
    tool2d  
       2024 年 3 月 21 日
    @githmb OP 贴出来的 SpringBoot API 回调不行,带有 MultipartFile file 参数,就必须等数据上传完成,才会触发回调函数。

    有你说的提前匹配,要用另外的 API 。
    NessajCN
        6
    NessajCN  
       2024 年 3 月 21 日
    那你自己在服务端写个先验证再接收的过程呗....
    这样客户端再传的时候就分两部,先一个小的请求,包含文件名,大小,验证信息之类的,
    返回一个 token
    第二个请求的 headers 里必须带上这个 token
    yolee599
        7
    yolee599  
       2024 年 3 月 21 日
    服务器的问题,应该限制一下 Body 的大小,太大就返回 413 Payload Too Large 就行,如果不限制就是会接收完整个 Body 才发送 Response ,HTTP 协议就是这样
    lazyczx
        8
    lazyczx  
    OP
       2024 年 3 月 21 日
    @tool2d
    可是 url 都错了,还会和这个参数有关吗。
    提前匹配的 API 是啥,我感觉这个能解决问题。
    lazyczx
        9
    lazyczx  
    OP
       2024 年 3 月 21 日
    @NessajCN
    你说的这种方法,可以先验证 token 再接受 `请求本体` 吗?
    如果不行的话,似乎还是没解决问题。
    如果可以的话,似乎这个和楼上说的提前验证的方法本质上一样,那么是用的什么 API 呢?
    NessajCN
        10
    NessajCN  
       2024 年 3 月 21 日
    @lazyczx 可以,就是验 headers 就好,不符合直接返回 401, 不需要收 body. 基本所有服务端库都支持
    lazyczx
        11
    lazyczx  
    OP
       2024 年 3 月 21 日
    @NessajCN
    太感谢了,我用 Jakarta filter 成功实现了,先验证 Header 再接收请求体。

    有网友帮太幸福了!!~~~谢谢
    NessajCN
        12
    NessajCN  
       2024 年 3 月 21 日
    @lazyczx 不客气,问题解决就好
    realJamespond
        13
    realJamespond  
       2024 年 3 月 22 日
    可以用 blob 分片上传大文件
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5511 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 49ms UTC 07:12 PVG 15:12 LAX 00:12 JFK 03:12
    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