I need to download query results from an endpoint by streaming results to a CSV file. This is in an effort to support enormous ResultSets being sent through the browser at one time.
Is there a way to accomplish this using Axios in the context of a React App?
I have seen fetch() and know that it has the following characteristics:
Besides the ReadableStream
response type, the rest of the characteristics listed are not permissible. I will need to support IE11 and allow for intercepting requests / reading the HTTP status to determine how to handle the traffic.
fetch
: // The promise returned by `fetch` rejects if the fetch was unable to make HTTP-request
// e.g. network problems, or there’s no such site.
// Abnormal HTTP-statuses, such as 404 or 500 do not cause an error.
const results = await fetch(`${URL}/data`, {
method: 'post', // HTTP POST to send query to server
headers: {
Accept: 'application/json, text/plain, */*', // indicates which files we are able to understand
'Content-Type': 'application/json', // indicates what the server actually sent
},
body: JSON.stringify(query), // server is expecting JSON
credentials: 'include', // sends the JSESSIONID cookie with the address
}).then(res => res.json()) // turn the ReadableStream response back into JSON
.then((res) => {
if (res.ok) {
// boolean, true if the HTTP status code is 200-299.
console.log('response.ok!');
} else if (res.status === 401) {
throw Error(`You are not authenticated. Please login.`);
} else if (res.status === 403) {
throw Error(`You are not authorized to access this data.`);
} else {
throw Error(`Request rejected with status ${res.status}`);
}
})
.catch((error) => {
// catches error case and if fetch itself rejects
error.response = {
status: 0,
statusText:
'Cannot connect. Please make sure you are connected to internet.',
};
throw error;
});
console.log(results);
axios
(not streaming)import ...
const Api = axios.create({
baseURL: `${URL}`,
withCredentials: true,
});
// attach interceptors to requests and responses
// these are defined elsewhere and imported
Api.interceptors.request.use((request) => requestHandler(request));
Api.interceptors.response.use((response) => successHandler(response), (error) => errorHandler(error));
export default Api;
const query = {"selections":{"TABLE_A":["COLUMN1"]},"filters":[{"predicates":[]}],"joins":[],"sorts":[],"limit":100,"offset":0}
const response = await Api.post('/data', query);
// further transformations to response to get formatted csv results required
ReadableStream
in Axios same as fetch
? responseType: 'stream'
isn't something that can be done in the browser, only with Node.js using fs
fetch
or something else in conjunction with Axios?Step 1: Below is the command to create React app in your project… Step 2: Enter in the directory created in the first step. Step 3: Install Axios library using the command given below… Step 4: Once this has been done, you can start the server using the command given below..
Fortunately Axios supports a “stream” response type, but it wasn't nearly as straight forward as I would have liked when attempting to use it with async / await syntax.
Streaming a response from the browser is not currently supported :
https://github.com/axios/axios/issues/479
Since we're dealing with XMLHttpRequests
in the browser, Axios is limited to the specification set by whatwg
. :
Specifically, these are the only supported types :
enum XMLHttpRequestResponseType {
"",
"arraybuffer",
"blob",
"document",
"json",
"text"
};
stream
is accepted when setting a responseType
in axios, but this is misleading. The adapter is going to be xhr.js
implicitly since we are using the browser which relies on XMLHttpRequests. HttpRequests are made on the server-side and will allow axios to use the http.js
adapter. THEN you can use stream
as a ResponseType with Node.js.
Using the fetch
API seems to be the only solution with a ReadableStream
as a response body type.
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