I have a (Spring Boot 1.5) REST server handling file uploads (multipart/form-data
) and a JS client using jQuery fileupload. In most cases it works fine but when I want to upload a larger file (about 4MB), the server figures out it is above the limit and sends back a response including the error message.
However it seems the server stops reading the request (which is of course right) which results in a broken pipe on client side. In this case the response is not handled. The fail
callback is called with the following content of data.jqXHR
(data.response
is undefined):
{"readyState":0,"responseText":"","status":0,"statusText":"error"}
When doing the call using curl
, the result is:
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
curl: (55) Send failure: Broken pipe
{"files":[{"size":3863407,"error":"upload_uploadSizeExceeded"}]}
So there is a response returned but it seems to be ignored by the JS client. Is there any option to make jQuery handle the response even if the request is sent only partially?
BTW: even more strange, I see the request repeated several times in the server log in such a case, maybe a kind of retry mechanism in JS?
The best way to bubble that error from the server side (using php) to the client side is to send a header through the Ajax request somewhere in the 400's (which is always associated with errors). Once the Ajax request receives this it will trigger your error function.
When there is an AJAX error response or the AJAX request times out, you'll want to log as much information as you have, including the error message that jQuery gives you, the url and the request data. $. ajax(url, { "data": requestData, "type": "POST", "timeout": 5000 }) .
Cut and paste whatever code you need to execute in the callback function passed to success . Some good answer is already provided.
What you need to do is pass a callback function to the somefunction as a parameter. This function will be called when the process is done working (ie, onComplete): somefunction: function(callback){ var result = ""; myAjax = new Ajax.
Is there any option to make jQuery handle the response even if the request is sent only partially?
No, browsers use XMLHttpRequest and Fetch API, and this is considered a network error, by the specification, and network errors are intentionally empty.
CURL does not handle responses according to XMLHttpRequest specification.
Read the request's ReadableStream and cancel mid-way:
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);
I carefully inspected each event and there is no indication of Sent bytes. If we did have a Sent bytes value, which should be in loaded
, we could know if the request was cancelled midway to handle this case without the response:
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));
Unfortunately, nothing.
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.
From the 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.
I was hoping to intercept a low-level ReadableStream and get something, but, unfortunately, the resolve callback is not called on network errors:
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
Browsers do not treat this as an HTTP error, but a network error, and therefore do not forward anything HTTP related to user code.
XHR and Fetch specification states that network errors are handled as empty responses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With