| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| #import "CMISHttpDownloadRequest.h" |
| #import "CMISErrors.h" |
| #import "CMISLog.h" |
| |
| @interface CMISHttpDownloadRequest () |
| |
| @property (nonatomic, copy) void (^progressBlock)(unsigned long long bytesDownloaded, unsigned long long bytesTotal); |
| @property (nonatomic, assign) unsigned long long bytesDownloaded; |
| - (id)initWithHttpMethod:(CMISHttpRequestMethod)httpRequestMethod |
| completionBlock:(void (^)(CMISHttpResponse *httpResponse, NSError *error))completionBlock |
| progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock; |
| |
| @end |
| |
| |
| @implementation CMISHttpDownloadRequest |
| |
| |
| + (id)startRequest:(NSMutableURLRequest *)urlRequest |
| httpMethod:(CMISHttpRequestMethod)httpRequestMethod |
| outputStream:(NSOutputStream*)outputStream |
| bytesExpected:(unsigned long long)bytesExpected |
| authenticationProvider:(id<CMISAuthenticationProvider>) authenticationProvider |
| trustedSSLServer:(BOOL)trustedSSLServer |
| completionBlock:(void (^)(CMISHttpResponse *httpResponse, NSError *error))completionBlock |
| progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock |
| { |
| CMISHttpDownloadRequest *httpRequest = [[self alloc] initWithHttpMethod:httpRequestMethod |
| completionBlock:completionBlock |
| progressBlock:progressBlock]; |
| httpRequest.outputStream = outputStream; |
| httpRequest.bytesExpected = bytesExpected; |
| httpRequest.authenticationProvider = authenticationProvider; |
| httpRequest.trustedSSLServer = trustedSSLServer; |
| |
| if ([httpRequest startRequest:urlRequest] == NO) { |
| httpRequest = nil; |
| }; |
| |
| return httpRequest; |
| } |
| |
| |
| - (id)initWithHttpMethod:(CMISHttpRequestMethod)httpRequestMethod |
| completionBlock:(void (^)(CMISHttpResponse *httpResponse, NSError *error))completionBlock |
| progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock |
| { |
| self = [super initWithHttpMethod:httpRequestMethod |
| completionBlock:completionBlock]; |
| if (self) { |
| _progressBlock = progressBlock; |
| } |
| return self; |
| } |
| |
| |
| - (void)cancel |
| { |
| [self.outputStream close]; |
| |
| self.progressBlock = nil; |
| |
| [super cancel]; |
| } |
| |
| |
| - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response |
| { |
| [super connection:connection didReceiveResponse:response]; |
| |
| // update statistics |
| if (self.bytesExpected == 0 && response.expectedContentLength != NSURLResponseUnknownLength) { |
| self.bytesExpected = response.expectedContentLength; |
| } |
| self.bytesDownloaded = 0; |
| |
| // set up output stream if available |
| if (self.outputStream) { // otherwise store data in memory in self.data |
| // create file for downloaded content |
| BOOL isStreamReady = self.outputStream.streamStatus == NSStreamStatusOpen; |
| if (!isStreamReady) { |
| [self.outputStream open]; |
| isStreamReady = self.outputStream.streamStatus == NSStreamStatusOpen; |
| } |
| |
| if (!isStreamReady) { |
| [connection cancel]; |
| |
| if (self.completionBlock) |
| { |
| NSError *cmisError = [CMISErrors createCMISErrorWithCode:kCMISErrorCodeStorage |
| detailedDescription:@"Could not open output stream"]; |
| self.completionBlock(nil, cmisError); |
| } |
| } |
| } |
| } |
| |
| |
| - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data |
| { |
| if (self.outputStream == nil) { // if there is no outputStream then store data in memory in self.data |
| [super connection:connection didReceiveData:data]; |
| } else { |
| const uint8_t *bytes = data.bytes; |
| NSUInteger length = data.length; |
| NSUInteger offset = 0; |
| do { |
| NSUInteger written = [self.outputStream write:&bytes[offset] maxLength:length - offset]; |
| if (written <= 0) { |
| CMISLogError(@"Error while writing downloaded data to file"); |
| [connection cancel]; |
| return; |
| } else { |
| offset += written; |
| } |
| } while (offset < length); |
| } |
| |
| // update statistics |
| self.bytesDownloaded += data.length; |
| // pass progress to progressBlock |
| if (self.progressBlock) { |
| self.progressBlock(self.bytesDownloaded, self.bytesExpected); |
| } |
| |
| } |
| |
| |
| - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error |
| { |
| [self.outputStream close]; |
| |
| self.progressBlock = nil; |
| |
| [super connection:connection didFailWithError:error]; |
| } |
| |
| |
| - (void)connectionDidFinishLoading:(NSURLConnection *)connection |
| { |
| [self.outputStream close]; |
| |
| self.progressBlock = nil; |
| |
| [super connectionDidFinishLoading:connection]; |
| } |
| |
| @end |