如何使用 fetch() 从请求中获取响应的内容长度

Posted

技术标签:

【中文标题】如何使用 fetch() 从请求中获取响应的内容长度【英文标题】:How to get the content-length of the response from a request with fetch() 【发布时间】:2018-06-24 07:14:26 【问题描述】:

返回response.json() 时遇到错误,当时我将使用空响应正文进行请求,因此我试图在有空正文时仅返回一个空对象。我想要的方法是检查响应的Content-Length 标头,但是,response.headers.get('Content-Length') 不知何故返回null。这是我的代码:

function fetchJSON(url, options, state = null) 
    return fetch(url, Object.assign(, options, 
            // TODO: Add options here that should be there for every API call
            // TODO: Add token if there is one
        ))
        .then(response => 
            // Pass the JSON formatted body to the next handler
            if (response.ok === true) 
                if (response.headers.get('Content-Length') === 0) return ;
                return response.json();
            

            // If the response was not an 2xx code, throw the appropriate error
            if (response.status === 401) throw new AuthorizationError("You are not authorized to perform this action");

            // If it is an error code that we did not expect, throw an regular error and hope that it gets noticed by
            // a developer
            throw new Error("Unexpected response: " + JSON.stringify(response));
        );

您能帮我找到回复的Content-Length 或帮我找到另一种方法吗?

【问题讨论】:

【参考方案1】:

你可以这样做:

 if (response.ok === true) 
        if (response.getResponseHeader("Content-Length") === 0) return ;
        return response.json();
 

或者像这样更容易:

 if (response.ok === true) 
        if (response.length === 0) return ;
        return response.json();
 

你没事吧? :)

【讨论】:

response.getResponseHeader("Content-Length") 返回undefined,而response.length 也是undefined,见developer.mozilla.org/en-US/docs/Web/API/Response 不成功的响应也可以包含json【参考方案2】:

服务器应在服务器端使用Access-Control-Expose-Headers 公开标头:

Access-Control-Expose-Headers: Content-Length

@sideshowbarker comment 解释了为什么您可以在浏览器的网络面板中看到标题,但当您看到 response.headers.get("Content-Length") 时却收到 null

仅仅因为您的浏览器接收到标题并且您可以看到 devtools 中的标头并不意味着您的前端 javascript 代码可以看到 它。如果来自跨域请求的响应没有 Access-Control-Expose-Headers:Content-Length 响应 — 如所示 在这个答案中 - 那么是您的浏览器本身会阻止您的 代码从能够访问标题。对于跨域请求, 您的浏览器只会向您的浏览器公开特定的响应标头 前端 JavaScript 代码(如果 Access-Control-Expose-Headers 值) 包含该特定标头的名称。

您可以通过将其复制/粘贴到控制台来查看它的工作原理:

fetch("//***.com").then(response => console.log(response.headers.get("content-length")))

请注意,Headers.get 的返回值将是一个字节串,因此您必须将其转换为数字才能在数值表达式中使用它:

Number(response.headers.get("content-length")) > 0

【讨论】:

问题不在于响应中没有标头,在 Google Chrome 的开发人员视图中我可以看到 Content-Length 标头实际上是 0,但是 response.headers.get("Content-Length") 返回 null @jbakker 仅仅因为您的浏览器接收到标头并且您可以在 devtools 中看到标头并不意味着您的前端 JavaScript 代码可以看到它。如果来自跨域请求的响应没有 Access-Control-Expose-Headers: Content-Length 响应(如本答案所示),那么是您的浏览器本身将阻止您的代码访问标头.对于跨域请求,如果 Access-Control-Expose-Headers 值包含特定标头的名称,您的浏览器只会向前端 JavaScript 代码公开特定的响应标头。 出色的答案,在实现下载进度指示器时让我摸不着头脑 Chromium 79, 80 为没有Access-Control-Expose-Headers 的跨域请求公开了此标头。【参考方案3】:

我刚刚解决了我的问题,只需将 response.json() 放入 try/catch 块并捕获在我尝试解析空正文时发生的错误。这不是理想的解决方案,但对我有用。

【讨论】:

【参考方案4】:

最后,您可以保持代码干净,只需编写if (response.ok)

【讨论】:

正如 Ted Elliott 所说“不成功的响应仍然可以包含 json”

以上是关于如何使用 fetch() 从请求中获取响应的内容长度的主要内容,如果未能解决你的问题,请参考以下文章

如何从 fetch 中获取响应的标头

在前端使用 fetch 从 express.js 服务器获取响应

Fetch API 从响应中获取原始值

如何从fetch获取响应值而不是没有值的promise?

如何在本地使用 fetch 从客户端向服务器发出请求而不会得到不透明的响应?

使用 fetch API 从数组中获取数据的问题 [重复]