HTTP是否允许服务器在使用所有输入之前启动输出?如果是这样,如何在Java中访问这样的服务器?

HTTP是否允许服务器在使用所有输入之前启动输出?如果是这样,如何在Java中访问这样的服务器?,java,http,urlconnection,Java,Http,Urlconnection,注意:这个问题与以下区别密切相关:(1)我没有发送错误,我发送的是200 OK,以及(2)我同时控制客户端和服务器,因此并不真正关心浏览器支持 上下文:我正在实现一个用于管理文件的Java HTTP客户端和服务器。特别是“上传”查询包含文件路径和文件正文,服务器用文件的数字标识符进行响应。但是,如果已经上载了具有相同路径的文件,服务器将仅使用先前生成的标识符进行响应 具体地说:如果我按照以下方式编写服务器(sparkjava) 。。。然后,服务器将使用id进行响应,并在客户端完成数据发送之前关闭

注意:这个问题与以下区别密切相关:(1)我没有发送错误,我发送的是200 OK,以及(2)我同时控制客户端和服务器,因此并不真正关心浏览器支持

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

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

。。。然后,服务器将使用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()));
然后,由于连接关闭,在
copy
操作期间引发
IOException
。在此之后,我无法再访问连接的
InputStream


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

假设文件足够大,并且多个请求比传输一个部分文件消耗的资源少得多,您可以将该调用中断到多个请求中

enum上载状态{
初始化,
起动,
上传,
错误
}
我的建议:

  • 拥有一个静态映射
    ConcurrentMap
    (或DB 条目),您可以在其中跟踪文件上载状态
  • 创建端点以检查和设置文件状态
  • 客户端首先向上述端点发出请求
    • 如果映射上存在文件且其状态不是
      UploadStatus.ERROR
      ,请将映射上的文件状态设置为
      UploadStatus.INITIALIZED
      ,并让客户端(客户端A)知道它可以上载文件(应在
      synchronized
      块上执行此操作)
  • 如果文件存在并且
    UploadStatus.INITIALIZED
    ,请让该客户端(客户端B)知道其正在上载。为了用户体验,您可以对文件状态进行客户端B轮询,直到
    UploadStatus
    变为
    ERROR
    UPLOADED
    ,然后采取适当的操作。即
    • 在上载状态下重新上载文件。错误
    • 在上传状态下显示上传消息。上传
  • 一旦服务器从客户端A接收到上载实际文件的请求,请保持文件上载状态为最新,以便在出现错误时,其他客户端(如客户端B)可以重新上载失败的文件

  • 在设置正确的文件状态时,在单个同步块上执行文件状态检查和设置对于避免争用情况非常重要。此外,该枚举只是为了解释一般的高级步骤。既然你已经有了番石榴,你可以使用时基驱逐来存储文件状态。

    问题:如果用户想要上传“更新”版本的视频怎么办?该文件将包含相同的路径(包括文件)名称,但用户将不能,因为它将接收以前加载的文件的标识符。一般来说,如果尚未接收到所有请求,则无法处理请求。您可以做的是两步操作:1)检查文件是否已加载。如果是,返回标识符-如果不是,2)上载文件-两个单独的requests@blurfus:谢谢你的评论。1.上载的文件在我的应用程序中是显式不可变的。2.一些人回答了相关的问题,说应该允许这样做(至少在返回错误时是这样,但不确定2xx的情况)。3.对于我的情况来说,两步方法确实不错,但是我仍然想知道在我目前的情况下哪个服务器或客户端是错误的。我可能会使用与浏览器进行XSS检查相同的方法:他们进行飞行前检查(对预期URL的头请求)-如果头不包含必要的信息/头,它们不会继续执行实际的HTTP请求。这类似于:发送POST请求的简化版本(即带有文件路径的GET请求),并查看响应是否为404(即未找到)。如果是,则继续POST,否则使用上述方法从响应(或其他合适的处理)@tendays中检索ID,尝试同时上载相同文件的客户端将在其初始GET请求中看到相同的结果,即找不到文件,因为它不在服务器上,两个客户端都将开始上载文件。感谢详细建议。您是说,在当前状态下,服务器违反了HTTP协议吗?我应该向Sparkjava框架提交一个bug吗?我认为您使用的任何组件都没有问题。只是任务的性质要求您具有某种原子性。i、 e.从第一个客户端开始检查文件是否存在到文件上载结束,其他客户端都不能上载文件。这些类型的东西不是HTTP协议或Spark框架的一部分,用户需要实现它们。我真正感兴趣的是知道早期HTTP 200回答是否允许,如果允许,Java客户机如何处理。不过,我非常感谢您花时间编写答案并对其进行投票。如果您提前返回HTTP 200(我想您的意思是当文件已经上载时),java客户端可以让用户知道该文件已经存在。或者你可以发送一个409,说有人已经上传了相同的文件。但是当你收到回复时,完全由你来决定你想如何去做
    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()));