POST 上传完成之前重定向

发布于 2024-09-03 00:12:45 字数 248 浏览 7 评论 0原文

我有带有文件上传的表格。上传的文件实际上是图片和视频,因此它们可能会很大。我有基于标头和前 1KB 的逻辑可以确定其余部分是否将被处理或立即拒绝。在后一种情况下,我想将客户端重定向到错误页面,而不必等待上传完成。

实际情况是,仅在 POST 完成之前发送响应似乎不起作用。重定向被忽略,如果我关闭连接,浏览器会抱怨“连接被对等方重置”错误。

所以问题是:是否有可能在纯 HTTP 中做到这一点(客户端无需 JavaScript),如果可以,如何实现?

I have form with file upload. The files to be uploaded actually are pictures and videos, so they can be quite big. I have logic which based on headers and first 1KB can determine if the rest will be processed or immediately rejected. In the later case I'd like to redirect client to error page without having to wait for upload to finish.

The case is, that just sending response before POST is complete doesn't seem to work. The redirect gets ignored and if I close connection, browser complains with "Connection reset by peer" error.

So the question is: is it even possible to do that in pure HTTP (without JavaScript on client-side), and if so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

謌踐踏愛綪 2024-09-10 00:12:45

HTTP/1.1 协议确实允许这样做,只是以一种非常奇怪和混乱的方式。您需要应用以下 3 步过程:

  1. 立即(突然)关闭连接,为客户端会话存储服务器端标志
  2. 使用该标志来检测重新发送相同表单数据的尝试,规范建议客户端这样做自动
  3. 发送带有重定向的错误状态(如 302 暂时移动)

应该可以工作,因为如下所述,客户端在意外断开后至少会重试一次连接。在重试尝试时,预计仅发送标头,然后等待并观察错误响应,并在收到错误响应时中止发送正文。

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

8.2.4 服务器过早关闭连接时的客户端行为

如果 HTTP/1.1 客户端发送请求
其中包括请求主体,但是
其中不包括 Expect
请求标头字段
“100-继续”期望,如果
客户端没有直接连接到
HTTP/1.1 源服务器,并且如果
客户端看到连接关闭
在收到任何状态之前
服务器,客户端应该重试
要求。如果客户端重试此操作
请求,它可以使用以下内容
“二元指数退避”算法
确保获得可靠的
回复:

 1. 发起与服务器的新连接

  2. 传输请求头

  3. 将变量 R 初始化为估计的往返时间
     服务器(例如,基于建立该服务器所花费的时间
     连接),或者如果轮询,则为 5 秒的恒定值
     行程时间不可用。

  4. 计算 T = R * (2**N),其中 N 是先前的数量
     重试此请求。

  5. 等待来自服务器的错误响应,或者等待 T
     秒(以先到者为准)

  6. 如果没有收到错误响应,则在 T 秒后发送
     请求正文。

  7. 如果客户端发现连接过早关闭,
     从步骤1开始重复,直到请求被接受,出现错误
     收到响应,或者用户变得不耐烦并且
     终止重试过程。

如果在任何时候出现错误状态
收到,客户端

 - 不应该继续并且

  - 如果尚未完成发送,则应关闭连接
    请求消息。

遇到的问题:

  1. 这就是规范所说的浏览器应该所做的事情。谁知道浏览器实际上做什么
    在这种情况下?不是我。您需要运行一些测试。
  2. 该规范特别提到,此行为仅适用于“如果客户端未直接连接到 HTTP/1.1 源服务器”。这似乎是一个非常奇怪的要求,实际上意味着您可能需要伪造服务器响应标头来假装您是代理或 HTTP/1.0 服务器。
  3. 在请求完成之前,某些中间协议(例如 fast-cgi)可能不会激活您的脚本。在这种情况下,您实际上需要一个真正的低级套接字服务器。
  4. 整个过程是混乱而复杂的,甚至可能行不通。我认为你最好使用 AJAX。不过,你确实问过是否可以不用 JS 来完成。

The HTTP/1.1 protocol does allow for this, just in a really bizarre and messed up way. You need to apply the following 3 step proceedure:

  1. Immediately (abruptly) close the connection, store a server-side flag for the client session
  2. Use the flag to detect an attempt to resend the same form data, the spec recommends the client to do this automatically
  3. Send an error status with a redirect (like 302 Temporarily Moved)

This SHOULD work because as outlined below the client is expected to retry a connection at least once after being cut off unexpectedly. On the retry attempt(s) it is expected to only send the headers, then wait and watch for an error response and abort sending the body if it gets one.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

8.2.4 Client Behavior if Server Prematurely Closes Connection

If an HTTP/1.1 client sends a request
which includes a request body, but
which does not include an Expect
request-header field with the
"100-continue" expectation, and if the
client is not directly connected to an
HTTP/1.1 origin server, and if the
client sees the connection close
before receiving any status from the
server, the client SHOULD retry the
request. If the client does retry this
request, it MAY use the following
"binary exponential backoff" algorithm
to be assured of obtaining a reliable
response:

  1. Initiate a new connection to the server

  2. Transmit the request-headers

  3. Initialize a variable R to the estimated round-trip time to the
     server (e.g., based on the time it took to establish the
     connection), or to a constant value of 5 seconds if the round-
     trip time is not available.

  4. Compute T = R * (2**N), where N is the number of previous
     retries of this request.

  5. Wait either for an error response from the server, or for T
     seconds (whichever comes first)

  6. If no error response is received, after T seconds transmit the
     body of the request.

  7. If client sees that the connection is closed prematurely,
     repeat from step 1 until the request is accepted, an error
     response is received, or the user becomes impatient and
     terminates the retry process.

If at any point an error status is
received, the client

  - SHOULD NOT continue and

  - SHOULD close the connection if it has not completed sending the
    request message.

Gotchas:

  1. That's what the spec says browswers SHOULD do. Who knows what browsers ACTUALLY do
    in this case? Not me. You'll need to run some tests.
  2. The spec makes a specific mention that this behaviour only applies "if the client is not directly connected to an HTTP/1.1 origin server". That seems a really bizarre requirement which in practice means you may need to fake your server response headers to pretend you're a proxy or HTTP/1.0 server.
  3. Certain intermediary protocols like fast-cgi may not activate your script until the request is complete. In this event you'll actually need a real low-level socket server.
  4. This whole process is messy and convoluted and may not even work. You'd be better off using AJAX in my opinion. Still, you did ask if it could be done without JS.
苄①跕圉湢 2024-09-10 00:12:45

看看 django 票证 #10850 - “无法在中途停止大文件上传”。不能解决问题,但至少可以帮助你理解它。

Have a look at django ticket #10850 - "Impossible to stop a large file upload mid-stream". Doesn't solve the problem, but at least it should help you understand it.

放低过去 2024-09-10 00:12:45
  1. 使用 PCEL uploadprogress 扩展如果您使用 apache
  2. 创建一个文件通过 Ajax 轮询元,并根据您的条件返回 true 或 false,您还可以获取 temp_name 文件并检查 1kb 元。
  3. ajax 调用需要与一个函数绑定,该函数使用 HTML 元刷新标头来重定向或停留到上传完成为止。

查看上传进度示例。

  1. use PCEL uploadprogress extension if you use apache
  2. create an file to poll meta via Ajax, and return trueor false based on your condition, you could also get the temp_name file and check for the 1kb meta.
  3. the ajax call need to be binded with an function which uses HTML meta-refresh headers to redirect or stay until the uploads done.

Checkout the uploadprogress examples.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文