【问题标题】:iOS NSURLConnection not downloading files from certain URLsiOS NSURLConnection 不从某些 URL 下载文件
【发布时间】:2013-04-30 22:28:22
【问题描述】:

我在可以下载大多数文件的 tableview 单元子类中有一个 NSURLConnection。但是,我注意到有些无法开始下载并超时。一个例子是this URL,它只是一个测试 zip 文件,可以在任何其他浏览器中正常下载。这是我的下载代码

-(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);
}

有人看到可能导致这种情况的任何东西吗?

这是错误:

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."}

【问题讨论】:

  • 实现connection:didFailWithError: 协议方法,看看你得到了什么错误。
  • @Malloc 我的错,我忘记发布了。它只是说连接超时。
  • 好的,那么你得到的错误堆栈是什么?
  • 您尝试从同一服务器下载的所有文件吗?超时错误纯粹是服务器端。
  • 我的问题中的链接在 Safari 上下载,而不是在我的手机上。这就是为什么我认为它与我的下载有关,因为它也发生在其他文件上。

标签: ios objective-c nsurlconnection


【解决方案1】:

“我在 tableview 单元子类中有一个 NSURLConnection” - 永远不要这样做。正如 Sung-Pil Lim 已经正确指出的那样,TableView Cells 将被重用,这可能会导致这个问题。

无论如何,您连接的响应数据是模型的属性。该模型可能会封装它如何获取这些数据。如果该数据一旦被访问就不能立即可用,它应该提供一个“占位符”值,并启动一个异步任务来检索该数据。

假设一个模型的属性,一个图像,将被视图控制器访问以便被视图显示。该模型尚未加载其实际图像 - 因此它返回一个“占位符图像”以让视图显示某些内容。但与此同时,模型正在启动一个异步任务来加载图像。当此连接完成数据加载后,模型会在内部更新其属性 - 从而将占位符替换为真实图像。属性的更新应该在主线程上执行 - 因为 UIKit 视图也可以访问相同的属性。

在初始化期间,视图控制器已注册为模型属性的观察者(请参阅 KVO)。当模型的属性更新时,控制器会收到通知。视图控制器然后执行适当的操作,以便重新绘制视图并显示新的更新值。

您的模型应该有一个“取消”方法,当不再需要模型属性的实际值时,该方法将从控制器发送到模型。例如,用户切换到另一个视图(请参阅 viewWillDisappear)。

【讨论】:

    【解决方案2】:

    我试过你的代码。

    - (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
    

    它正在工作......在 ViewController 上

    “请求超时错误”被带到网络连接。或者...

    你在重新使用 UITableViewCell 吗?如果您初始化单元重用代码处理连接。也许会带来麻烦。只是我想。

    如果您附加更多代码。我能帮你更多吗?

    【讨论】:

      【解决方案3】:

      我会从头开始,只使用基本代码进行下载。加载大量 NSLog(s) 以跟踪所有内容。如果可行,请继续添加您的自定义代码,看看您是否偶然发现错误。我建议基本的 NSURLConnection 代码:

      -(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");
      }
      

      【讨论】:

        【解决方案4】:

        尝试使用 HCDownloadViewController,您可以检查未下载的 url。下次同步未下载的特定网址。

        .h 文件

        #import "HCDownloadViewController.h"
        @interface HomeViewController_iPhone : UIViewController<HCDownloadViewControllerDelegate>
        {
            HCDownloadViewController *tblDownloadHairStyle;
        
        }
        @property (nonatomic,retain) HCDownloadViewController *tblDownloadHairStyle;
        

        .m 文件

        #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

        【讨论】:

          【解决方案5】:

          接受 http 响应代码范围为 200-299 的任何响应,并禁用 http-connector 上的缓存。

          【讨论】:

            【解决方案6】:

            仔细检查您的 url 地址是否符合 RFC 2396。因此它必须包含 HTTP://

            【讨论】:

              【解决方案7】:

              项目中是否有任何库(TestFlight、UA 等)?尝试删除它们并重新测试。我们有一个使用 NSUrlConnection 和 TestFlight SDK 的应用程序,导致各种零星的网络问题。

              NSURLConnection timing out

              ASIHTTPRequest request times out

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

              【讨论】:

              • 第一个链接“NSURLConnection 超时”指的是无论如何都不太可能正常工作的代码 - 因此不能很好地表明真正的问题。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-09-07
              • 2011-06-05
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多