gpt4 book ai didi

ajax - 发生管道损坏时如何处理 AJAX 响应?

转载 作者:行者123 更新时间:2023-12-04 08:50:42 27 4
gpt4 key购买 nike

我有一个(Spring Boot 1.5)REST 服务器处理文件上传(multipart/form-data)和一个使用 jQuery 文件上传的 JS 客户端。在大多数情况下,它工作正常,但是当我想上传一个更大的文件(大约 4MB)时,服务器发现它超出了限制并发送回包含错误消息的响应。

但是,服务器似乎停止读取请求(这当然是正确的),这导致客户端管道损坏。在这种情况下,不处理响应。 fail回调被调用,内容如下data.jqXHR (data.response 未定义):

{"readyState":0,"responseText":"","status":0,"statusText":"error"}

使用 curl 调用电话时,结果是:
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8

curl: (55) Send failure: Broken pipe
{"files":[{"size":3863407,"error":"upload_uploadSizeExceeded"}]}

所以有一个响应返回,但它似乎被 JS 客户端忽略了。即使仅部分发送请求,是否有任何选项可以让 jQuery 处理响应?

BTW:更奇怪的是,在这种情况下,我在服务器日志中看到请求重复了几次,可能是JS中的一种重试机制?

最佳答案

Is there any option to make jQuery handle the response even if the request is sent only partially?



简答

不,浏览器使用 XMLHttpRequest 和 Fetch API,这被规范认为是网络错误,并且网络错误是故意为空的。

CURL 不根据 XMLHttpRequest 规范处理响应。

长答案

模拟服务器

读取请求的 ReadableStream 并中途取消:
const http = require('http');

const server = http.createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Content-Type', 'text/plain');

//Close Request ReadableStream Prematurely
//to simulate close pipe on exceed file size
if (req.url === '/data' && req.method === 'POST') {
console.log('simulating...');

let i = 0;
req.on('data', chunk => {
if (i++ === 10)
req.destroy('broken pipe');
});
}

res.end('fooby\n');
}).listen(8080);

客户端测试

方法一:XMLHttpRequests

我仔细检查了每个事件,没有任何已发送字节的迹象。如果我们确实有一个 Sent bytes 值,它应该在 loaded ,我们可以知道请求是否在中途取消以处理这种情况而没有响应:
let req = new XMLHttpRequest();
req.open('POST', 'http://localhost:8080/data');
req.onloadstart = function (event) {
console.log(event);
};
req.onprogress = function (event) {
console.log(event);
};
req.onabort = function (event) {
console.log(event);
};
req.onerror = function (event) {
console.log(event);
};
req.onload = function (event) {
console.log(event);
};
req.ontimeout = function (event) {
console.log(event);
};
req.onloadend = function (event) {
console.log(event);
};
req.onreadystatechange = function (event) {
console.log(event);
};
req.send(new ArrayBuffer(100000000));

不幸的是,什么都没有。

The read-only XMLHttpRequest.status property returns the numerical status code of the response of the XMLHttpRequest. status will be an unsigned short. Before the request is complete, the value of status will be 0. It is worth noting that browsers report a status of 0 in case of XMLHttpRequest errors too.



来自 XMLHttpRequest specification :

A response whose type is "error" is known as a network error.

A network error is a response whose status is always 0, status message is always the empty byte sequence, header list is always empty, body is always null, and trailer is always empty.



方法二:获取 API

我希望拦截一个低级别的 ReadableStream 并得到一些东西,但是,不幸的是,在网络错误上没有调用解析回调:
fetch('http://localhost:8080/data', {
method: 'POST',
body: new ArrayBuffer(100000000),
mode: 'cors'
}).then(resp => {
console.log(resp);
//hopefully we can get readable stream here
//...nope, networkerrors do not trigger resolve
}).catch(error => {
console.log(error);//TypeError: "NetworkError when attempting to fetch resource."
}).then(retry => {
console.log(retry);
});

A fetch() promise rejects with a TypeError when a network error is encountered, although this usually means a permissions issue or similar. An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true. An HTTP status of 404 does not constitute a network error.



Fetch Documentation

Fetch Specification

浏览器不会将此视为 HTTP 错误,而是网络错误,因此不会转发任何与用户代码相关的 HTTP。

结论

XHR 和 Fetch 规范规定网络错误作为空响应处理。

关于ajax - 发生管道损坏时如何处理 AJAX 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51965462/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com