[React Native][iOS] XHR upload progress events

This commit is contained in:
Philipp von Weitershausen 2015-07-20 22:44:51 -07:00
parent 151ddd9e42
commit 9c5fe3612d
5 changed files with 64 additions and 0 deletions

View File

@ -128,6 +128,7 @@ class FormUploader extends React.Component {
super(props); super(props);
this.state = { this.state = {
isUploading: false, isUploading: false,
uploadProgress: null,
randomPhoto: null, randomPhoto: null,
textParams: [], textParams: [],
}; };
@ -217,6 +218,14 @@ class FormUploader extends React.Component {
this.state.textParams.forEach( this.state.textParams.forEach(
(param) => formdata.append(param.name, param.value) (param) => formdata.append(param.name, param.value)
); );
if (xhr.upload) {
xhr.upload.onprogress = (event) => {
console.log('upload onprogress', event);
if (event.lengthComputable) {
this.setState({uploadProgress: event.loaded / event.total});
}
};
}
xhr.send(formdata); xhr.send(formdata);
this.setState({isUploading: true}); this.setState({isUploading: true});
} }
@ -251,6 +260,10 @@ class FormUploader extends React.Component {
</View> </View>
)); ));
var uploadButtonLabel = this.state.isUploading ? 'Uploading...' : 'Upload'; var uploadButtonLabel = this.state.isUploading ? 'Uploading...' : 'Upload';
var uploadProgress = this.state.uploadProgress;
if (uploadProgress !== null) {
uploadButtonLabel += ' ' + Math.round(uploadProgress * 100) + '%';
}
var uploadButton = ( var uploadButton = (
<View style={styles.uploadButtonBox}> <View style={styles.uploadButtonBox}>
<Text style={styles.uploadButtonLabel}>{uploadButtonLabel}</Text> <Text style={styles.uploadButtonLabel}>{uploadButtonLabel}</Text>

View File

@ -75,6 +75,16 @@ RCT_EXPORT_MODULE()
#pragma mark - NSURLSession delegate #pragma mark - NSURLSession delegate
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
[[_delegates objectForKey:task] URLRequest:task didUploadProgress:(double)totalBytesSent total:(double)totalBytesExpectedToSend];
}
- (void)URLSession:(NSURLSession *)session - (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)task dataTask:(NSURLSessionDataTask *)task
didReceiveResponse:(NSURLResponse *)response didReceiveResponse:(NSURLResponse *)response

View File

@ -184,6 +184,11 @@ typedef void (^RCTDataLoaderCallback)(NSData *data, NSString *MIMEType, NSError
return [self initWithRequest:nil handler:nil callback:nil]; return [self initWithRequest:nil handler:nil callback:nil];
} }
- (void)URLRequest:(id)requestToken didUploadProgress:(double)progress total:(double)total
{
RCTAssert([requestToken isEqual:_requestToken], @"Shouldn't ever happen");
}
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response - (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response
{ {
RCTAssert([requestToken isEqual:_requestToken], @"Shouldn't ever happen"); RCTAssert([requestToken isEqual:_requestToken], @"Shouldn't ever happen");
@ -395,6 +400,17 @@ RCT_EXPORT_MODULE()
#pragma mark - RCTURLRequestDelegate #pragma mark - RCTURLRequestDelegate
- (void)URLRequest:(id)requestToken didUploadProgress:(double)progress total:(double)total
{
dispatch_async(_methodQueue, ^{
RCTActiveURLRequest *request = [_activeRequests objectForKey:requestToken];
RCTAssert(request != nil, @"Unrecognized request token: %@", requestToken);
NSArray *responseJSON = @[request.requestID, @(progress), @(total)];
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUploadProgress" body:responseJSON];
});
}
- (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response - (void)URLRequest:(id)requestToken didReceiveResponse:(NSURLResponse *)response
{ {
dispatch_async(_methodQueue, ^{ dispatch_async(_methodQueue, ^{

View File

@ -21,15 +21,23 @@ class XMLHttpRequest extends XMLHttpRequestBase {
_requestId: ?number; _requestId: ?number;
_subscriptions: [any]; _subscriptions: [any];
upload: {
onprogress?: (event: Object) => void;
};
constructor() { constructor() {
super(); super();
this._requestId = null; this._requestId = null;
this._subscriptions = []; this._subscriptions = [];
this.upload = {};
} }
_didCreateRequest(requestId: number): void { _didCreateRequest(requestId: number): void {
this._requestId = requestId; this._requestId = requestId;
this._subscriptions.push(RCTDeviceEventEmitter.addListener(
'didUploadProgress',
(args) => this._didUploadProgress.call(this, args[0], args[1], args[2])
));
this._subscriptions.push(RCTDeviceEventEmitter.addListener( this._subscriptions.push(RCTDeviceEventEmitter.addListener(
'didReceiveNetworkResponse', 'didReceiveNetworkResponse',
(args) => this._didReceiveResponse.call(this, args[0], args[1], args[2]) (args) => this._didReceiveResponse.call(this, args[0], args[1], args[2])
@ -44,6 +52,17 @@ class XMLHttpRequest extends XMLHttpRequestBase {
)); ));
} }
_didUploadProgress(requestId: number, progress: number, total: number): void {
if (requestId === this._requestId && this.upload.onprogress) {
var event = {
lengthComputable: true,
loaded: progress,
total,
};
this.upload.onprogress(event);
}
}
_didReceiveResponse(requestId: number, status: number, responseHeaders: ?Object): void { _didReceiveResponse(requestId: number, status: number, responseHeaders: ?Object): void {
if (requestId === this._requestId) { if (requestId === this._requestId) {
this.status = status; this.status = status;

View File

@ -15,6 +15,12 @@
*/ */
@protocol RCTURLRequestDelegate <NSObject> @protocol RCTURLRequestDelegate <NSObject>
/**
* Call this when you first receives a response from the server. This should
* include response headers, etc.
*/
- (void)URLRequest:(id)requestToken didUploadProgress:(double)progress total:(double)total;
/** /**
* Call this when you first receives a response from the server. This should * Call this when you first receives a response from the server. This should
* include response headers, etc. * include response headers, etc.