1

助けがあれば本当にできる問題があります

NSURLconnection を使用して大きなファイル (27MB) をダウンロードしています。ネットワークの中断がない場合、コードは正常に機能します。ネットワークの問題と部分的にダウンロードされたファイルのみを許可するために、ダウンロードされたファイルの量を確認し、サーバー要求を使用して不足している部分をダウンロードするコードを追加しました。

ファイルの一部をダウンロードし、実行中のプログラムを停止してから再度実行すると、コードは正常に機能します。ダウンロードは中断したところから開始され、完全なファイルが得られます。

ただし、プログラムを停止せずにもう一度ダウンロード ボタンを押すと、didReceiveData は 1 回だけ呼び出され、ファイルに 200KB だけ追加され、ファイルが正常にダウンロードされたことが通知されます。

助けてください-私は自分が間違っていることを理解しようと何年も費やしてきました.

以下のコード:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;

    NSLog(@"Response code = %d",httpResponse.statusCode );
     file = [NSFileHandle fileHandleForUpdatingAtPath:filename] ;// file is in .h


    if (file)   {
       [file seekToEndOfFile];
    }

}




- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{

    if (file)  {

        [file seekToEndOfFile];
        NSLog(@"file is %@",file);

    }

    [self.file writeData:data];
 }




- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{

    if([[NSFileManager defaultManager] fileExistsAtPath:filename])
    {
       [file closeFile];
        file = nil;
        theConnection = nil;
        filename = nil;
        theRequest = nil;
     }
     NSLog(@"Connection failed! Error - %@ %@",
     [error localizedDescription],
     [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{

    [file closeFile];
    file = nil;
    theConnection = nil;
    filename = nil;

}


- (IBAction)downloadFile:(id)sender {


    filename = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:movie1]; // filename is in .h file

    theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:movieDownload1]                                          cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

    NSUInteger downloadedBytes = 0;
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:filename]) {
        NSError *error = nil;
        NSDictionary *fileDictionary = [fm attributesOfItemAtPath:filename error:&error];
        if (!error && fileDictionary)
        downloadedBytes = [fileDictionary fileSize];
    } else {
        [fm createFileAtPath:filename contents:nil attributes:nil];
    }

    if (downloadedBytes > 0) {
         NSString *requestRange = [NSString stringWithFormat:@"bytes=%d-",downloadedBytes];
        [theRequest setValue:requestRange forHTTPHeaderField:@"Range"];
    }

    theConnection = nil;
    theConnection = [NSURLConnection connectionWithRequest:theRequest delegate:self];

   }
4

1 に答える 1

0

didReceiveResponse と didReceiveData で seekToEndOfFile を使用する代わりに、次のコード スニペットを試すことができます。それは私にとってはうまくいきました。

- (id)initWithURL:(NSString *)downloadString
{
    if (![super init])
        return nil;

    // Construct the URL to be downloaded
    self.downloadURL = [[NSURL alloc]initWithString:downloadString];
    self.downloadData = [[NSMutableData alloc] init];
    self.downloadedFilename   =   [[self.downloadURL path] lastPathComponent];

    [self downloadFile];

    return self;
}

-(void) downloadFile
{
    // set the filePath
    docFolderPath = [NSHomeDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: @"Documents/%@", self.downloadedFilename]];

    self.downloadStream = [NSOutputStream outputStreamToFileAtPath:docFolderPath append:NO];

    if (!self.downloadStream)
    {
        self.error = [NSError errorWithDomain:[NSBundle mainBundle].bundleIdentifier
                                         code:-1
                                     userInfo:@{@"message": @"Unable to create      NSOutputStream", @"function" : @(__FUNCTION__), @"path" : self.downloadedFilename}];

        return;
    }
    [self.downloadStream open];

    self.downloadConnection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self];
    [self.downloadConnection start];
}

//code snippet for the Resume functionality after your downloading gets paused/cancel

-(void) resumeInterruptedDownload
{
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:docFolderPath])
    {
        NSError *error = nil;
        NSDictionary *fileDictionary = [fm attributesOfItemAtPath:docFolderPath
                                                            error:&error];
        if (!error && fileDictionary)
            self.downloadedBytes = [fileDictionary fileSize];


    } else
    {
        [fm createFileAtPath:docFolderPath contents:nil attributes:nil];
    }


    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];

    // Define the bytes we wish to download.

    if(self.downloadedBytes != 0)
    {
        NSString *range = [NSString stringWithFormat:@"bytes=%i-", self.downloadedBytes];
        [request setValue:range forHTTPHeaderField:@"Range"];
    }

    // Data should immediately start downloading after the connection is created.

    self.downloadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:TRUE];
}

Mbs 単位の大きなファイルの場合は完全に機能しましたが、Kbs 単位の小さなファイルの場合は失敗することがあります。これらすべての NSURLConnection のデリゲート メソッドを試す必要はありません。できることの 1 つは、各状態 (キャンセル、一時停止、ダウンロード中、ダウンロード済み) にマクロを設定して、いつダウンロードを再開したいかを知ることができるようにすることです。また、次のhttp://nachbaur.com/blog/resuming-large-downloads-with-nsurlconnectionを試すこともできます。

返信するには遅すぎることは承知していますが、IOS に入ったばかりです。これを試したら、うまくいったかどうか教えてください。ありがとう :) :)

于 2014-01-03T12:35:40.037 に答える