如何用JavaScript的fetch API仅从HTTP请求中获取前N个字节内容?
不下载完整资源检测文件类型的实现方案
方案1:通过Range请求头仅获取指定长度内容
- 可以在fetch请求中添加
Range请求头,设置值为bytes=0-1023即可请求资源的前1KB内容 - 需判断响应状态码:返回
206 Partial Content代表服务器支持Range请求,返回的响应体就是你需要的部分内容;如果返回200代表服务器不支持Range请求,响应体为完整资源,需要配合流处理避免加载全部内容
方案2:通过ReadableStream截断请求(兼容性更好)
不管服务器是否支持Range请求,都可以通过读取响应流的指定长度后直接中止请求,实现不下载完整资源的效果,配合file-type包即可实现文件类型检测,示例代码如下:
// 安装依赖:npm install file-type import { fileTypeFromBuffer } from 'file-type'; async function getRemoteFileType(url) { const res = await fetch(url); const reader = res.body.getReader(); const chunks = []; let received = 0; // 绝大多数文件的魔数都存在于前4KB区间,足够完成检测 const needLength = 4 * 1024; while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); received += value.length; if (received >= needLength) { // 读取到足够内容后直接取消请求,终止后续资源下载 await reader.cancel(); break; } } // 拼接已读取的二进制内容 const buffer = new Uint8Array(received); let pos = 0; for (const chunk of chunks) { buffer.set(chunk, pos); pos += chunk.length; } // 返回检测到的文件类型,包含ext、mime等字段 return await fileTypeFromBuffer(buffer); }
补充说明
- 两种方案可以搭配使用:优先发送带Range头的请求减少传输量,服务器不支持Range时再用流截断的方式处理
- 4KB的读取阈值是行业通用的最优值,覆盖了几乎所有格式的魔数存储位置,比1KB的检测成功率更高
内容的提问来源于stack exchange,提问作者Frido Emans
相关产品推荐
相关产品推荐

