Objective-C Проверить размер загружаемого файла - PullRequest
2 голосов
/ 18 февраля 2011

Я создаю приложение, которое загружает ZIP-файл с сервера S3. Все работает отлично. Теперь я хочу прервать текущую загрузку. Если бы я мог сохранить текущий размер (в байтах) файла, я бы смог отправить новый запрос с заголовком диапазона для другой части файла.

Проблема заключается в том, что я не могу определить размер уже загруженного контента, потому что я могу видеть файл в своем каталоге только после завершения загрузки. Поэтому, если я прерву, частичный файл не будет сохранен.

В настоящее время для этого я использую следующий код:

 -(void) downloadFile:(NSMutableArray*)paramArray withDict:(NSMutableDictionary*)options
 {

NSLog(@"DOWNLOAD THREAD STARTED");
NSString * sourceUrl = [paramArray objectAtIndex:0];
NSString * fileName = [paramArray objectAtIndex:1];

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];    

NSString *newFilePath = [documentsDirectory stringByAppendingString:fileName];

NSError *error=[[[NSError alloc]init] autorelease]; 


NSURLConnection *fileURL = [NSData dataWithContentsOfURL: [NSURL URLWithString:sourceUrl]];

BOOL response = [fileURL writeToFile:newFilePath options:NSDataWritingFileProtectionNone error:&error]; 

if (response == TRUE)
{
    NSLog(@"DOWNLOAD COMPLETED");
    [self performSelectorOnMainThread:@selector(downloadComplete:withDict:) withObject:paramArray waitUntilDone:YES];
}
else 
{
    NSLog(@"Something went wrong while downloading file.");
    NSString *callback = [NSString stringWithFormat:@"downloadInterrupted('%@');",fileName];
    [webView stringByEvaluatingJavaScriptFromString:callback];

}

[pool drain];
}

AsiHTTP не вариант, потому что есть проблемы с PhoneGap, который я использую.

Ответы [ 3 ]

3 голосов
/ 18 февраля 2011

Лучшая идея - загрузить файл асинхронно. Это имеет несколько преимуществ: наиболее важным является то, что ваш пользовательский интерфейс остается отзывчивым. Пользователь может продолжать использовать ваше приложение во время загрузки и ожидания данных. Если данные, которые вы загружаете, абсолютно необходимы для приложения, отобразите какой-то индикатор загрузки.

Вы можете легко запустить асинхронную загрузку через

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:sourceUrl]];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];

Теперь, как мне получить данные загрузки в объекте NSData? Для self реализованы следующие методы делегата:

-connection:didReceiveData:
-connection:didFailWithError:
-connectionDidFinishLoading:

Идея состоит в том, что вы будете уведомлены, когда какие-либо данные попадают в ваше соединение или происходит что-то важное (например, успех или ошибка). Таким образом, вы собираетесь объявить временный объект NSMutableData в качестве переменной экземпляра (скажем, downloadData) и записывать его до завершения загрузки. Не забудьте инициализировать пустой объект и объявить свойство!

-connection:didReceiveData: вызывается всякий раз, когда поступают какие-либо данные (то есть часть вашего загруженного файла). Итак, вы собираетесь добавить его к вашему временному объекту так:

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

После завершения загрузки (успешно) вызывается следующий метод делегата:

-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
    //do whatever you need to do with the data in self.downloadData
}

Если загрузка не удалась, вызывается -connection:didFailWithError:. Затем вы можете сохранить временный объект, получить его размер и продолжить загрузку позже. [self.downloadData length]; возвращает вам размер в байтах данных вашего объекта.

1 голос
/ 18 февраля 2011

Вам нужно будет использовать API нижнего уровня.

время, чтобы прочитать о программировании сокетов Unix. http://www.fortunecity.com/skyscraper/arpanet/6/cc.htm было бы хорошим началом.

Это действительно не будет слишком сложно. честны.

0 голосов
/ 18 февраля 2011

Я рекомендую вам создать метод, который будет сохранять порцию данных каждые 1, 2 МБ или меньше, чтобы правильно возобновить загрузку и избежать сбоя памяти. Это потому, что если вы получите ошибку в вашем переводе, возможно, ваш файл может быть поврежден.

В любом случае отправить диапазон HTML-заголовок довольно просто

NSFileHandle *fileHandler = [NSFileHandle fileHandleForReadingAtPath:dataPreviouslySavedPath];
[fileHandler seekToEndOfFile];
unsigned long long int range = [fileHandler offsetInFile];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[request setValue:[NSString stringWithFormat:@"bytes=%lli-", range] forHTTPHeaderField:@"Range"];

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...