上传获取的进度指标?

时间:2016-02-29 23:20:08

标签: javascript html5 fetch-api

我很难找到使用fetch实施上传进度指示的文档或示例。

This is the only reference I've found so far,其中声明:

  

进度事件是一项高级功能,暂时无法获取。您可以通过查看Content-Length标头并使用直通流来监控收到的字节来创建自己的。

     

这意味着您可以不同地Content-Length显式处理响应。当然,即使Content-Length存在,也可能是谎言。使用流可以随心所欲地处理这些谎言。

如何编写“传输流以监控字节”发送?如果它产生任何差异,我正试图通过浏览器将图像上传到Cloudinary

注意:我 Cloudinary JS library感兴趣,因为它依赖于jQuery而我的应用却没有。我只对使用原生javascript和Github的fetch polyfill进行此处所需的流处理感兴趣。

https://fetch.spec.whatwg.org/#fetch-api

7 个答案:

答案 0 :(得分:33)

Streams开始登陆网络平台(https://jakearchibald.com/2016/streams-ftw/),但现在还处于早期阶段。

很快你就可以提供一个流作为请求的主体,但是开放的问题是该流的消耗是否与上传的字节有关。

特定重定向可能导致数据重新传输到新位置,但流不能重新启动"。我们可以通过将主体转换为可以多次调用的回调来解决这个问题,但是我们需要确保暴露重定向的数量不是安全漏洞,因为它是第一次出现在平台JS可以检测到。

有些人质疑将流消费链接到上传的字节是否有意义。

长话短说:这还不可能,但将来这将通过流处理,或者传递到fetch()的某种更高级别的回调来处理。

答案 1 :(得分:9)

我的解决方案是使用axios,它非常支持这个:

      axios.request( {
        method: "post", 
        url: "/aaa", 
        data: myData, 
        onUploadProgress: (p) => {
          console.log(p); 
          //this.setState({
            //fileprogress: p.loaded / p.total
          //})
        }


      }).then (data => {
        //this.setState({
          //fileprogress: 1.0,
        //})
      })

我在github.

的反应中使用了这个例子

答案 2 :(得分:7)

我不认为这是可能的。该草案指出:

  

当涉及到请求进展时,它目前缺少[与XHR 相比]

(旧回答):
Fetch API chapter中的第一个示例提供了有关如何:

的一些见解
  

如果您想逐步接收身体数据:

function consume(reader) {
  var total = 0
  return new Promise((resolve, reject) => {
    function pump() {
      reader.read().then(({done, value}) => {
        if (done) {
          resolve()
          return
        }
        total += value.byteLength
        log(`received ${value.byteLength} bytes (${total} bytes in total)`)
        pump()
      }).catch(reject)
    }
    pump()
  })
}

fetch("/music/pk/altes-kamuffel.flac")
  .then(res => consume(res.body.getReader()))
  .then(() => log("consumed the entire body without keeping the whole thing in memory!"))
  .catch(e => log("something went wrong: " + e))

除了使用Promise constructor antipattern之外,您还可以看到response.body是一个Stream,您可以使用Reader从中逐字节读取,您可以触发事件或执行任何您喜欢的操作(例如记录进度)每个人。

但是,Streams spec似乎没有完成,我不知道这是否已经在任何获取实现中都有效。

答案 3 :(得分:3)

可能的解决方法是使用new Request()构造函数,然后检查Request.bodyUsed Boolean属性

  

如果bodyUseddisturbed属性的getter必须返回true   否则就是假的。

确定流是否为distributed

  

实现Body mixin的对象被称为disturbed if   body为非空,其streamdisturbed

fetch()等于{{1}时,将Promise .then().read()链接到ReadableStream的递归Request.bodyUsed来电。 }}

注意,当字节流式传输到端点时,该方法不会读取true的字节。此外,在将任何响应完全返回给浏览器之前,上传可以很好地完成。

Request.body

答案 4 :(得分:1)

type AddRow = SqlCommandProvider<"path to the parameterized INSERT statement", designTimeConnection> 
..............................
(new AddRow(runTimeConnection, commandTimeOut=timespan)).Execute(...arg=value...) |> ignore

感谢此链接:https://jakearchibald.com/2016/streams-ftw/

答案 5 :(得分:0)

const req = await fetch('./foo.json');
const total = Number(req.headers.get('content-length'));
let loaded = 0;
for await(const {length} of req.body.getReader()) {
  loaded = += length;
  const progress = ((loaded / total) * 100).toFixed(2); // toFixed(2) means two digits after floating point
  console.log(`${progress}%`); // or yourDiv.textContent = `${progress}%`;
}

答案 6 :(得分:-1)

关键部分是ReadableStream«obj_response。body。

样品:

let parse=_/*result*/=>{
  console.log(_)
  //...
  return /*cont?*/_.value?true:false
}

fetch('').
then(_=>( a/*!*/=_.body.getReader(), b/*!*/=z=>a.read().then(parse).then(_=>(_?b:z=>z)()), b() ))

您可以测试在大页面上运行它,例如https://html.spec.whatwg.org/https://html.spec.whatwg.org/print.pdf。 CtrlShiftJ并加载代码。

(在Chrome上测试过。)