You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

服务器不支持Range头时,浏览器如何仅获取图片前1300字节生成占位符?

问题

我希望在图片完全加载前,仅从URL获取1300字节的图片来生成占位符。针对一张2.12KB的图片,我尝试使用XMLHttpRequest的progress事件:

req.addEventListener("progress", (ev) => {
        console.log("loaded bytes", ev.loaded); // 2179
    })

但第一次触发事件时,ev.loaded的值为2179,即整个文件已下载,这不符合我的需求。而使用Python的requests库开启stream模式并设置chunk_size=1300时,成功将1300字节写入文件:

with requests.get(url , stream=True) as response:
    for chunk in response.iter_content(chunk_size=1300):
        print(len(chunk)) # 1300
        with open("test.jpg" , "wb") as f:
            f.write(chunk)
            break

假设服务器不接受Range头,请问浏览器中是否有对应的API可以实现该功能?

回答

浏览器中没有像Python requests那样能精准控制只获取指定字节的原生API,这是因为浏览器的HTTP请求处理受限于底层TCP传输策略、服务器响应方式(比如小文件会一次性发送)以及浏览器缓存机制,很难像后端请求库那样细粒度控制数据流。不过可以通过以下方式实现近似需求:

使用Fetch API结合ReadableStream与AbortController

通过Fetch的响应体ReadableStream逐块读取数据,当累计读取字节达到1300时,立即中断请求,同时截取已读取的前1300字节使用:

const controller = new AbortController();
const targetBytes = 1300;

fetch('目标图片URL', { signal: controller.signal })
  .then(response => {
    const reader = response.body.getReader();
    let receivedBytes = 0;
    const chunkList = [];

    return reader.read().then(function processChunk({ done, value }) {
      if (done) {
        // 若文件本身小于1300字节,直接使用全部数据
        const buffer = new Uint8Array(receivedBytes);
        let offset = 0;
        chunkList.forEach(chunk => {
          buffer.set(chunk, offset);
          offset += chunk.length;
        });
        console.log('文件小于目标字节数,已获取全部:', receivedBytes);
        // 这里用buffer生成占位符
        return;
      }

      receivedBytes += value.length;
      chunkList.push(value);

      if (receivedBytes >= targetBytes) {
        // 达到目标字节数,中断请求
        controller.abort();
        // 截取前1300字节
        const limitedBuffer = new Uint8Array(targetBytes);
        let offset = 0;
        for (const chunk of chunkList) {
          const takeLength = Math.min(chunk.length, targetBytes - offset);
          limitedBuffer.set(chunk.subarray(0, takeLength), offset);
          offset += takeLength;
          if (offset >= targetBytes) break;
        }
        console.log('已获取目标字节数:', offset);
        // 这里用limitedBuffer生成占位符
      } else {
        // 继续读取下一块
        return reader.read().then(processChunk);
      }
    });
  })
  .catch(err => {
    if (err.name !== 'AbortError') {
      console.error('请求异常:', err);
    }
  });

局限性说明

对于2.12KB这类小文件,服务器大概率会一次性发送完整响应,此时浏览器会直接接收全部数据,即使中断请求也已经拿到了整个文件。但这种情况下,你依然可以在客户端只截取前1300字节来生成占位符,同样能满足需求——只是会多下载几百字节的冗余数据。

内容的提问来源于stack exchange,提问作者Momo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 20:20:24