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

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

  •  
  •   lazyczx · 238 天前 · 1458 次点击
    这是一个创建于 238 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想实现一个 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  
       238 天前
    和 gpt 说,用 ajax 来上传文件,可以控制上传进度。

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

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

    有网友帮太幸福了!!~~~谢谢
    NessajCN
        12
    NessajCN  
       238 天前
    @lazyczx 不客气,问题解决就好
    realJamespond
        13
    realJamespond  
       238 天前
    可以用 blob 分片上传大文件
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4081 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:27 · PVG 13:27 · LAX 21:27 · JFK 00:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.