AFNetworking 2 Загрузка данных Plist на сервер Apache

Я пишу пример приложения, чтобы проверить, как AFNetworking может использоваться в качестве замены для ASIHTTPLib. Старая библиотека упростила загрузку файла на сервер Apache (при условии, что пользователь имеет право на запись в URL/каталог). Никакой другой поддержки на стороне сервера не используется.

У этого кода есть некоторые проблемы, но я не определил его: выполнение метода сообщает об успешности загрузки, но файл plist на стороне облака не изменяется...

-(void)uploadReminders:(NSArray*)reminders
{
 NSLog(@"AppDelegate Synch Reminders to cloud");
 //NSLog(@"Data: %@", reminders);

 [self persistReminders:reminders atCustomPath:nil];

 NSString *cacheDirectoryPath = [self cachesDirectoryPath];

 NSString *urlString = [NSString stringWithFormat:@"%@/%@",kStandardCloudAreaAccessURL,kStandardLocalCachePlistFile];
 //NSLog(@"URL: %@", urlString);
 NSString *remindersPlistFile = [NSString stringWithFormat:@"%@/%@",cacheDirectoryPath,kStandardLocalCachePlistFile];
 //NSLog(@"Filepath: %@",remindersPlistFile);

 NSURLCredential *defaultCredential = [NSURLCredential credentialWithUser:kStandardCloudAreaAccessUsername password:kStandardCloudAreaAccessUserPW persistence:NSURLCredentialPersistenceNone];

 /**/
 NSURL *url = [NSURL URLWithString:urlString];

 NSString *host = [url host];
 NSInteger port = [[url port] integerValue];
 NSString *protocol = [url scheme];

 NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];

 NSURLCredentialStorage *credentials = [NSURLCredentialStorage sharedCredentialStorage];
 [credentials setDefaultCredential:defaultCredential forProtectionSpace:protectionSpace];

 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
 [configuration setURLCredentialStorage:credentials];
 [configuration setHTTPAdditionalHeaders: @{@"Accept": @"text/plain"}];

 AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
 [manager.securityPolicy setAllowInvalidCertificates:YES];

 manager.responseSerializer = [AFPropertyListResponseSerializer serializer];
 manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/plain"];

 NSURL *URL = [NSURL URLWithString:urlString];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];
 NSURL *filePath = [NSURL fileURLWithPath:remindersPlistFile];

 NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {

 if (error) {

 NSLog(@"Upload Error: %@", error);

 } else {

 //NSLog(@"Upload Success");
 NSLog(@"Upload Success: %@ %@", response, responseObject);
 }
 }];

 [uploadTask resume];

}

Консоль показывает это:

Upload Success: <nshttpurlresponse: 0x8d4ec50=""> { URL: https://[.....]/CodeTests/Reminders/Reminders.plist } { status code: 200, headers {
 "Accept-Ranges" = bytes;
 Connection = "Keep-Alive";
 "Content-Length" = 1324;
 "Content-Type" = "text/plain";
 Date = "Mon, 10 Mar 2014 14:48:13 GMT";
 Etag = "\"3f06e5-52c-4f430180dae80\"";
 "Keep-Alive" = "timeout=5, max=100";
 "Last-Modified" = "Sun, 09 Mar 2014 17:48:26 GMT";
 Server = "Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.7l DAV/2";
} } {
 reminders = (
 {
 completed = 1;
 created = "2014-03-09 17:47:41 +0000";
 description = "";
 title = Reminder;
 updated = "2014-03-09 17:47:41 +0000";
 },
 {
 completed = 1;
 created = "2014-03-08 09:47:58 +0000";
 description = "Orza!!! Ma orza in fretta... Ah: funziona? ******, s\U00ec! O no?\n";
 title = "Reminder Orza";
 updated = "2014-03-08 11:39:43 +0000";
 },
 {
 completed = 0;
 created = "2014-03-07 11:09:59 +0000";
 description = "Whatever you like; and of course you can even make it quite long.\n\nYeooww..\nReally long!\n\n\n\n";
 title = "Reminder A";
 updated = "2014-03-08 11:34:24 +0000";
 }
 );
 version = "1.0";
}
</nshttpurlresponse:>

Единственный улов в том, что когда я снова открываю приложение, он возвращается к тестовым напоминаниям, которые я вручную загрузил на сервер: Reminders.plist никогда не менялся.

Благодарю!

1 ответ

Я предполагаю, что ваш NSLog объекта responseObject подтверждает, что plist был успешно получен сервером. Если это так, то это может исключить вышеупомянутый код "загрузить" в качестве источника проблемы. Вы можете просмотреть данные на своем сервере (не через приложение, а вручную проверить его самостоятельно) и посмотреть, есть ли у вас новый список напоминаний. Кажется, существует пара возможных логических возможностей:

  • Если обновленных данных там нет, то посмотрите на логику "сохранить" на сервере, так как она, кажется, не работает.

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

В таких случаях инструмент, подобный Чарльзу, может быть полезен, когда вы можете проверить запросы и ответы, которые вы получаете. Это может быть полезно при сужении именно там, где возникает проблема.

Познакомившись с вашим запросом, я заметил, что вы не указываете тип запроса. Я бы подумал, что ваш запрос будет POST:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:@"POST"];
[request setValue:@"text/plain" forHTTPHeaderField:@"Accept"]; // I'd also personally set the 'Accept' here at the request, not at the 'NSURLSessionConfiguration'

Сказав это, учитывая, что ваш веб-сервис успешно сообщает вам данные о plist, я бы предположил, что он успешно получил его на основании доказательств, которыми вы поделились с нами до сих пор. Но, возможно, отказ сделать запрос POST запрос означает, что веб-служба пришла к выводу, что ничего не нужно ничего сохранять.

Как правило, при взаимодействии с веб-службой, а не в настройке запроса, как я уже AFHTTPSessionManager выше, я бы рекомендовал вам публиковать данные, используя один из стандартных вариантов AFHTTPSessionManager метода POST (один для запросов multipart/form-data, другой - для других запросов). Но я не могу понять, что делает ваш сервер на основе того, что вы предоставили до сих пор (например, нет никакого смысла в том, что сервер отправляет тело вашего запроса назад вам вообще, нет смысла, что сервер, похоже, получил ваш запрос, но ничего не делает с ним и не сообщает о некоторой ошибке и т.д.). Поэтому, возможно, попробуйте сделать запрос POST запрос и посмотреть, исправляет ли он это. Если нет, запустите Charles на свой старый исходный код ASIHTTP, и вы точно увидите, как выглядит старый запрос, и вы сможете воспроизвести его с помощью AFNetworking.

licensed under cc by-sa 3.0 with attribution.