iOS NSURLConnection not downloading files from cer

2019-04-29 02:57发布

I have an NSURLConnection in a tableview cell subclass that can download most files. I noticed, however, that some fail to start downloading, and time out. An example would be this URL, which is just a test zip file that downloads fine in any other browser. Heres my code for the download

-(void)downloadFileAtURL:(NSURL *)url{
    self.downloadedData = [[NSMutableData alloc] init];
    self.url = url;
    conn = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:self.url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:1200.0] delegate:self startImmediately:YES];
}

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response
{
    int statusCode = [response statusCode];
    if (statusCode == 200){
        self.fileName.text = response.URL.lastPathComponent;
        self.respo = response;
        expectedLength = [response expectedContentLength];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [self.downloadedData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    CFStringRef mimeType = (__bridge CFStringRef)[_respo MIMEType];
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
    CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
    NSString *fileName = [NSString stringWithFormat:@"%@.%@", [[_respo suggestedFilename] stringByDeletingPathExtension], (__bridge NSString *)extension];
    [[NSFileManager defaultManager] createFileAtPath:[[self docsDir] stringByAppendingPathComponent:[NSString stringWithFormat:@"Downloads/%@", fileName]] contents:_downloadedData attributes:nil];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"Download failed with error: %@", error);
}

Anybody see anything that might cause this?

Heres the error:

Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x1fd2c650 
{NSErrorFailingURLStringKey=http://download.thinkbroadband.com/10MB.zip, 
NSErrorFailingURLKey=http://download.thinkbroadband.com/10MB.zip, 
NSLocalizedDescription=The request timed out., NSUnderlyingError=0x1fdc90b0 "The request timed out."}

7条回答
ら.Afraid
2楼-- · 2019-04-29 03:36

try with HCDownloadViewController and you can check which url is not downloaded. and next time sync for that particular url which is not downloaded.

.h file

#import "HCDownloadViewController.h"
@interface HomeViewController_iPhone : UIViewController<HCDownloadViewControllerDelegate>
{
    HCDownloadViewController *tblDownloadHairStyle;

}
@property (nonatomic,retain) HCDownloadViewController *tblDownloadHairStyle;

.m file

#define kAppDirectoryPath   NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)

@synthesize tblDownloadHairStyle

- (void)viewDidLoad
{
    [super viewDidLoad];
     tblDownloadHairStyle=[[HCDownloadViewController alloc] init];
    tblDownloadHairStyle.delegate=self;
}
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response
{

    [self createDocumentDirectory:@"Downloaded_HairStyle"];
    NSString *pathHair=[self getDocumentDirectoryPath:@"Downloaded_HairStyle"];
    tblDownloadHairStyle.downloadDirectory = pathHair;
     ////You can put url in for loop, it create queue for downloading.
    [tblDownloadHairStyle downloadURL:[NSURL URLWithString:@"yourUrl"] userInfo:YourResponseDictonary];
}


-(void)createDocumentDirectory:(NSString*)pStrDirectoryName
{
    NSString *dataPath = [self getDocumentDirectoryPath:pStrDirectoryName];

    if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
        [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:NULL];
}

-(NSString*)getDocumentDirectoryPath:(NSString*)pStrPathName
{
    NSString *strPath = @"";
    if(pStrPathName)
        strPath = [[kAppDirectoryPath objectAtIndex:0] stringByAppendingPathComponent:pStrPathName];

    return strPath;
}


#pragma mark-
#pragma mark-HCDownloadViewController Delegate Method
- (void)downloadController:(HCDownloadViewController *)vc startedDownloadingURL:(NSURL *)url userInfo:(NSDictionary *)userInfo {

}

- (void)downloadController:(HCDownloadViewController *)vc finishedDownloadingURL:(NSURL *)url toFile:(NSString *)fileName userInfo:(NSDictionary *)userInfo {

    if (vc==tblDownloadHairStyle) {
       if ([tblDownloadHairStyle numberOfDownloads]==0) {

            NSLog(@"AllDownLoad are complete");
         }
    }
}
- (void)downloadController:(HCDownloadViewController *)vc failedDownloadingURL:(NSURL *)url withError:(NSError *)error userInfo:(NSDictionary *)userInfo {
     NSLog(@"failedDownloadingURL=%@",url);
}

https://github.com/H2CO3/HCDownload

查看更多
混吃等死
3楼-- · 2019-04-29 03:40

I tried your codes.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
  [self.downloadedData appendData:data];
  NSLog(@"%d", data.length);
}
2013-05-04 01:51:13.811 SomethingTodo[2732:c07] 1124
2013-05-04 01:51:13.856 SomethingTodo[2732:c07] 1448
2013-05-04 01:51:14.075 SomethingTodo[2732:c07] 1448
2013-05-04 01:51:17.180 SomethingTodo[2732:c07] 1448
2013-05-04 01:51:17.295 SomethingTodo[2732:c07] 1448

It's working... on ViewController

'request timeout error' was brought to network connection. or...

Are you resuing UITableViewCell? If you initialize for cell reuse codes deal with connection. maybe bring to trouble. Just i thought.

If you attach more your codes. Could I help you more then this.

查看更多
Melony?
4楼-- · 2019-04-29 03:52

Do you have any libraries (TestFlight, UA, etc) in the project? Try removing them and re-test. We had an app that used NSUrlConnection with TestFlight SDK that caused all sorts of sporadic network problems.

NSURLConnection timing out

ASIHTTPRequest request times out

https://github.com/AFNetworking/AFNetworking/issues/307

查看更多
我想做一个坏孩纸
5楼-- · 2019-04-29 03:55

I would start with a clean slate and just use basic code to work the download. Load in lots of NSLog(s) to track everything. If that works, keep adding your custom code and see if you stumble across an error. I suggest basic NSURLConnection code:

-(void)startDownloading:(NSString *)URLaddress{
NSLog(@"start downloading from: %@",URLaddress);
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:[URLaddress stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]
                                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                                      timeoutInterval:60.0];
__unused NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(@"didReceiveResponse: %@", response);
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(@"didReceiveData");
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(@"Connection failed! Error - %@ %@",[error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(@"connectionDidFinishLoading");
}
查看更多
虎瘦雄心在
6楼-- · 2019-04-29 03:56

"I have an NSURLConnection in a tableview cell subclass " - never do this. As Sung-Pil Lim already pointed out correctly, TableView Cells will be reused which may cause this issue.

Anyway, the response data of your connection is a property of the model. The model might encapsulate how it gets to this data. If that data is not immediately available once it will be accessed, it should provide a "placeholder" value instead and start an asynchronous task which retrieves this data.

Suppose a model's property, an image, will be accessed by the view controller in order to be displayed by a view. The model has not yet loaded its actual image - and thus it returns a "placeholder image" in order to let the view display something. But at the same time the model is starting an asynchronous task to load the image. When this connection is finished loading with the data, the model updates internally its property - thereby replacing the placeholder with the real image. The update of the property should be performed on the main thread - since the UIKit views may access the same property as well.

During initialization, the View Controller has registered as an observer of the model's property (see KVO). When the model's property is updated, the controller gets notified. The View Controller then performs appropriate actions so that the view will be redrawn and displays the new updated value.

Your model should have a "cancel" method, which will be send to the model from the controller when the actual value of the model's property is not required anymore. For example, the user switched to another view (see viewWillDisappear).

查看更多
爱情/是我丢掉的垃圾
7楼-- · 2019-04-29 03:57

accept any response with http response code range 200-299 and disable caching on the http-connector.

查看更多
登录 后发表回答