REST: 上传大文件

4
我想知道使用REST上传大文件的推荐方法。
鉴于从服务器将文件写入磁盘所需的时间可能很长,我应该在发送201响应给客户端之前等待写入操作结束吗?
也许即时回复用户并稍后处理写入操作会更好?在第二种情况下,我应返回什么HTTP状态码?事实上,即使我返回201,也无法确保写入操作成功。

我会等待所需的时间,返回的代码应该代表操作的最终状态。 - Florian F.
1个回答

4
似乎你在读取完HTTP的最后一个字节之前并没有开始向磁盘写入数据,这会导致两个不良影响:
  1. 将大量数据放入服务器的内存占用中
  2. 将所有磁盘IO都推迟到请求处理的末尾,导致客户端看起来很慢。在极端情况下,客户端可能会超时。
相反,你需要进行流式传输。只要从客户端获得了一些数据,就开始向磁盘写入。当客户端发送其最后一块数据时,你只需要处理该小块数据,然后发送201响应即可。
如果你使用的API不允许以流式方式消耗HTTP实体,则需要寻找其他API。
例如,在Java Servlet API中,你可以获取请求内容的InputStream:
InputStream content = request.getInputStream();

// do something better than this
OutputStream out = new FileOutputStream("content.txt");
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
    // whatever processing you want here
    out.write(buffer, 0, len);
}

// now you can send the 201

重要的是要理解,在此示例中获取InputStream时,您的服务器尚未开始从TCP堆栈读取内容(*). 只有标题已被读取。如果是大文件,则非常可能客户端此时仍在发送。您需要在循环中读取一块、写一块。

(*) 这是一个简化。它可以在缓冲区中。但在概念上,您可以忽略它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接