mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix onprogress not firing when Content-Length is not available for XMLHttpRequest (#44899)
Summary: When an XMLHttpRequest is performed, the `onprogress` event it is not invoked when the `Content-Length` header is missing in the response. This is the case when we are calling an endpoint that responds with `transfer-encoding: chunked` (https://tools.ietf.org/html/rfc9112#section-7.1), preventing the user to keep track of the progress while the server is sending chunks. Despite we will never know the total length of the content (because it will not be known due to the RFC specification, so it will be always `-1`), we will now be able to keep track of the loaded data. Note that in Android, this is the current default behaviour. To address this issue: - I removed the condition where the `downloadProgressBlock` was dispatched only when `response.expectedContentLength` was greater than 0 - I created a new test case for `XMLHttpRequest` in the tester app to download a chunked file ## Changelog: [IOS] [CHANGED] - fire `onprogress` event for `XMLHttpRequest` even when the `Content-Length` header is missing in the response headers Pull Request resolved: https://github.com/facebook/react-native/pull/44899 Test Plan: |before|after| |----------|:-------------:| |https://github.com/facebook/react-native/assets/37150312/6da3518f-eed3-4808-a2f8-abe26e5c7487|https://github.com/facebook/react-native/assets/37150312/ed1da300-dcf7-4874-a941-a2289f1cb777 Reviewed By: cortinico Differential Revision: D58562088 Pulled By: NickGerleman fbshipit-source-id: 23a1cafa49ddcd25fa0db7d04fae845126771425
This commit is contained in:
committed by
Facebook GitHub Bot
parent
9d637e4622
commit
457d14bd1b
@@ -190,7 +190,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
|
||||
incrementalDataBlock(data, length, total);
|
||||
}];
|
||||
}
|
||||
if (_downloadProgressBlock && total > 0) {
|
||||
if (_downloadProgressBlock) {
|
||||
RCTURLRequestProgressBlock downloadProgressBlock = _downloadProgressBlock;
|
||||
[self dispatchCallback:^{
|
||||
downloadProgressBlock(length, total);
|
||||
|
||||
@@ -40,6 +40,7 @@ class XHRExampleDownload extends React.Component<{...}, Object> {
|
||||
readystateHandler: false,
|
||||
progressHandler: true,
|
||||
arraybuffer: false,
|
||||
chunked: false,
|
||||
};
|
||||
|
||||
xhr: ?XMLHttpRequest = null;
|
||||
@@ -107,12 +108,19 @@ class XHRExampleDownload extends React.Component<{...}, Object> {
|
||||
Alert.alert('Error', xhr.responseText);
|
||||
}
|
||||
};
|
||||
xhr.open(
|
||||
'GET',
|
||||
'http://aleph.gutenberg.org/cache/epub/100/pg100-images.html.utf8',
|
||||
);
|
||||
// Avoid gzip so we can actually show progress
|
||||
xhr.setRequestHeader('Accept-Encoding', '');
|
||||
if (this.state.chunked) {
|
||||
xhr.open(
|
||||
'GET',
|
||||
'https://filesamples.com/samples/ebook/azw3/Around%20the%20World%20in%2028%20Languages.azw3',
|
||||
);
|
||||
} else {
|
||||
xhr.open(
|
||||
'GET',
|
||||
'http://aleph.gutenberg.org/cache/epub/100/pg100-images.html.utf8',
|
||||
);
|
||||
// Avoid gzip so we can actually show progress
|
||||
xhr.setRequestHeader('Accept-Encoding', '');
|
||||
}
|
||||
xhr.send();
|
||||
|
||||
this.setState({downloading: true});
|
||||
@@ -133,7 +141,11 @@ class XHRExampleDownload extends React.Component<{...}, Object> {
|
||||
) : (
|
||||
<TouchableHighlight style={styles.wrapper} onPress={this._download}>
|
||||
<View style={styles.button}>
|
||||
<Text>Download 7MB Text File</Text>
|
||||
<Text>
|
||||
{this.state.chunked
|
||||
? 'Download 10MB File'
|
||||
: 'Download 19KB pdf File'}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
@@ -188,6 +200,13 @@ class XHRExampleDownload extends React.Component<{...}, Object> {
|
||||
onValueChange={arraybuffer => this.setState({arraybuffer})}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.configRow}>
|
||||
<Text>transfer-encoding: chunked</Text>
|
||||
<Switch
|
||||
value={this.state.chunked}
|
||||
onValueChange={chunked => this.setState({chunked})}
|
||||
/>
|
||||
</View>
|
||||
{button}
|
||||
{readystate}
|
||||
{progress}
|
||||
|
||||
Reference in New Issue
Block a user