我很难找到使用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进行此处所需的流处理感兴趣。
答案 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
属性
如果
bodyUsed
,disturbed
属性的getter必须返回true 否则就是假的。
确定流是否为distributed
实现
Body
mixin的对象被称为disturbed
ifbody
为非空,其stream
为disturbed
。
当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
答案 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上测试过。)