POST jpeg upload с AFNetworking

Я не могу для жизни понять, почему это не работает, когда я использую AFNetworking. Он работал с ASIHTTP. Это все очень ново для меня. Но я не могу понять, почему файлы больше не переносятся с $ _FILES на HD-сервер. Вот код iOS:

- (IBAction)uploadPressed { [self.fileName resignFirstResponder]; NSURL *remoteUrl = [NSURL URLWithString:@"http://mysite.com"]; NSTimeInterval timeInterval = [NSDate timeIntervalSinceReferenceDate]; NSString *photoName=[NSString stringWithFormat:@"%lf-Photo.jpeg",timeInterval]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; // the path to write file NSString *filePath = [documentsDirectory stringByAppendingPathComponent:photoName]; NSData * photoImageData = UIImageJPEGRepresentation(self.remoteImage.image, 1.0); [photoImageData writeToFile:filePath atomically:YES]; NSLog(@"photo written to path: e%@", filePath); AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:remoteUrl]; NSMutableURLRequest *afRequest = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/photos" parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData) { [formData appendPartWithFormData:[self.fileName.text dataUsingEncoding:NSUTF8StringEncoding] name:@"name"]; [formData appendPartWithFileData:photoImageData name:self.fileName.text fileName:filePath mimeType:@"image/jpeg"]; } ]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest]; [operation setUploadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) { NSLog(@"Sent %d of %d bytes", totalBytesWritten, totalBytesExpectedToWrite); }]; [operation setCompletionBlock:^{ NSLog(@"%@", operation.responseString); //Gives a very scary warning }]; [operation start]; } 

Я это делал:

 ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:remoteUrl]; [request setPostValue:self.fileName.text forKey:@"name"]; [request setFile:filePath forKey:@"filename"]; [request setDelegate:self]; [request startAsynchronous]; 

Вот мой PHP:

  { // these could be stored in a .ini file and loaded // via parse_ini_file()... however, this will suffice // for an example $codes = Array( 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => '(Unused)', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported' ); return (isset($codes[$status])) ? $codes[$status] : ''; } function sendResponse($status = 200, $body = '', $content_type = 'text/html') { $status_header = 'HTTP/1.1 ' . $status . ' ' . getStatusCodeMessage($status); header($status_header); header('Content-type: ' . $content_type); echo $body; } if (!empty($_FILES) && isset($_POST["name"])) { $name = $_POST["name"]; $tmp_name = $_FILES['filename']['tmp_name']; $uploads_dir = '/var/www/cnet/photos'; move_uploaded_file($tmp_name, "$uploads_dir/$name.jpg"); $result = array("SUCCEEDED"); sendResponse(200, json_encode($result)); } else { sendResponse(400, 'Nope'); } ?> 

Попробуйте этот фрагмент кода:

  NSData* sendData = [self.fileName.text dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *sendDictionary = [NSDictionary dictionaryWithObject:sendData forKey:@"name"]; AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:remoteUrl]; NSMutableURLRequest *afRequest = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/photos" parameters:sendDictionary constructingBodyWithBlock:^(id <AFMultipartFormData>formData) { [formData appendPartWithFileData:photoImageData name:self.fileName.text fileName:filePath mimeType:@"image/jpeg"]; } ]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest]; [operation setUploadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) { NSLog(@"Sent %d of %d bytes", totalBytesWritten, totalBytesExpectedToWrite); }]; [operation setCompletionBlock:^{ NSLog(@"%@", operation.responseString); //Gives a very scary warning }]; [operation start]; 

Я не очень setPostValue:forKey: том, что делает ASI с помощью setPostValue:forKey: но вам может не setPostValue:forKey: параметр name для отправки отдельно от загрузки изображения.

Что именно происходит с клиентом или сервером? Выполняется ли ведение журнала выполнения?

Несколько других моментов:

  • Вы можете просто выполнить [operation start] в конце; не нужно создавать очередь операций только для этого.
  • Чтобы помочь с протоколированием, установите completionBlock на operation , с NSLog ответа или что-то в этом роде.
  • Возможно, вам захочется создать базовый класс AFHTTPClient с методом класса, чтобы вернуть экземпляр singleton, например, клиент API Gowalla в примере приложения AFNetworking. Затем этот клиент может управлять одной рабочей очередью для всех ваших сетевых запросов.

У меня есть обходной путь с использованием NSMutableURLRequest:

 NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:remoteUrl]; [req setHTTPMethod:@"POST"]; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data, boundary=%@", boundary]; [req setValue:contentType forHTTPHeaderField:@"Content-type"]; //adding the body: NSMutableData *postBody = [NSMutableData data]; [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"Content-Disposition: form-data; name=\"name\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[name dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"Content-Disposition: form-data; name=\"filename\";\r\nfilename=\"china.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[NSData dataWithData:imageData]]; [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [req setHTTPBody:postBody];