java - HTTP 是否允许服务器在消耗所有输入之前开始输出?如果是这样,如何用Java访问这样的服务器?

标签 java http urlconnection

注意:此问题与 Is it acceptable for a server to send a HTTP response before the entire request has been received? 密切相关区别在于(1)我没有发送错误,我发送的是 200 OK,(2)我控制客户端和服务器,所以并不真正关心浏览器支持。

上下文:我正在实现一个 Java HTTP 客户端和服务器来管理文件。特别是,“上传”查询包含文件路径和文件正文,并且服务器以文件的数字标识符进行响应。但是,如果已经上传了具有相同路径的文件,服务器将简单地使用之前生成的标识符进行响应。

具体:如果我按如下方式编写服务器(sparkjava)

put(url, (req, res) -> {
  Item existing = lookForExistingItem(req);
  if (existing != null) {
     return existing.getId();
  }
  /* Otherwise, consume input, save, generate id and return that */
});

...那么服务器会在客户端发送完数据之前响应该 id 并关闭连接。如果我按如下方式编写客户端:

final HttpURLConnection connection = (HttpURLConnection) new URL(...).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
ByteStreams.copy(fileInput, connection.getOutputStream());
final String response = CharStreams.toString(new InputStreamReader(connection.getInputStream()));

然后在复制操作期间由于关闭连接而抛出IOException。之后,我将无法再访问连接的 InputStream

我的问题:我怎样才能完成这项工作?如果我更改服务器以消耗整个输入并将其丢弃,它可以工作,但感觉像是浪费资源(某些正在上传的文件可能是重达数百兆字节的视频)。有没有办法改变客户端代码来处理这种情况?

最佳答案

假设文件足够大,并且发出多个请求比传输部分文件消耗的资源少得多,您可以将该调用分解为多个请求。

enum UploadStatus {
   INITIALIZED,
   STARTED,
   UPLOADED,
   ERROR
}

我的建议:

  1. 有静态 map ConcurrentMap<File name string, UploadStatus> (或数据库 条目)您可以在其中跟踪文件上传状态
  2. 创建端点来检查和设置文件状态
  3. 客户端首先向上述端点发出请求
    • 如果文件存在于 map 上且其状态不是 UploadStatus.ERROR ,将文件在 map 上的状态设置为 UploadStatus.INITIALIZED并让客户端(客户端 A)知道它可以上传文件(应该在 synchronized block 上执行此操作)
  4. 如果文件存在且 UploadStatus.INITIALIZED ,让该客户端(客户端 B)知道它正在上传。为了用户体验,您可以让客户端 B 轮询文件状态,直到 UploadStatus变成ERRORUPLOADED然后采取适当的行动。 IE。
    • UploadStatus.ERROR 上重新上传文件
    • 显示已上传的消息 UploadStatus.UPLOADED
  5. 服务器收到客户端 A 上传实际文件的请求后,请保持文件上传状态为最新,以便在出现错误时其他客户端(例如客户端 B)可以重新上传失败的文件。

在单个同步块(synchronized block)上进行文件状态检查和设置对于在设置正确的文件状态时避免竞争条件非常重要。此外,该枚举只是为了解释一般的高级步骤。由于您已经有了 Guava,您可以使用 Guava Cache使用时基驱逐来存储文件状态。

关于java - HTTP 是否允许服务器在消耗所有输入之前开始输出?如果是这样,如何用Java访问这样的服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62118768/

相关文章:

java - AbstractTableModel 不会更新 JTable

java - 使用 Java 类将文件上传到服务器

node.js - 对不同端口中不同应用程序的 http 请求

Java UrlConnection HTTP 1.0

Java URL连接

java - 将自定义 css 类附加到 SmartGWT 中 FormItem 的默认类

java - XMLPullParser 特殊字符

java - 如何使用JavaRDD类提取分组依据的计数?

http - 在HTTP服务器中提供静态文件

json - 如何从 Scala 中的 Http 响应实体中解码自定义对象?