首页 > 解决方案 > 在 React App 中使用 Axios 将响应数据下载为流

问题描述

问题

我需要通过将结果流式传输到 CSV 文件来从端点下载查询结果。这是为了支持一次通过浏览器发送大量的结果集。

有没有办法在 React App 的上下文中使用 Axios 来实现这一点?

我见过fetch()并且知道它具有以下特点:

除了ReadableStream响应类型之外,列出的其余特征都是不允许的。我需要支持 IE11 并允许拦截请求/读取 HTTP 状态以确定如何处理流量。

示例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(非流式传输)

Axios 实例

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;

axios 请求

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

关于 Axios 的问题

标签: javascriptnode.jsreactjsaxiosfetch

解决方案


当前不支持从浏览器流式传输响应:

https://github.com/axios/axios/issues/479

由于我们XMLHttpRequests在浏览器中处理,Axios 仅限于whatwg. :

具体来说,这些是唯一受支持的类型:

enum XMLHttpRequestResponseType {
  "",
  "arraybuffer",
  "blob",
  "document",
  "json",
  "text"
};

stream在 axios 中设置 a 时被接受responseType,但这是误导性的。xhr.js由于我们使用的是依赖于 XMLHttpRequests 的浏览器,因此适配器将是隐式的。HttpRequests 在服务器端进行,并允许 axios 使用http.js适配器。那么您可以将stream其用作 Node.js 的 ResponseType。

使用fetchAPI 似乎是唯一使用 aReadableStream作为响应主体类型的解决方案。


推荐阅读