2011-12-19 2 views
10

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

- (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'); 
      } 
?> 
+0

Некоторые комментарии: Вы должны использовать 'пустой ($ _ FILES)' вместо 'isset ($ _ FILES)' & '$ _FILES ['filename'] ['tmp_name']' вернет полный путь к загруженному файлу, поэтому файл move_uploaded_file не будет работать, если вы добавите 'error_reporting (E_ALL)' вверх вашего php-файла, тогда вы увидите ошибку ... –

+0

Спасибо! Я пошел вперед и сделал изменение от isset до! Пустым. И включил error_reporting. Но это от моего iPhone до сервера. Я не знаю, где я должен видеть ошибки. И в отношении синтаксиса move_uploaded_files я вытащил это прямо из руководства php http://php.net/manual/en/function.move-uploaded-file.php. –

+0

Я исправил PHP-код и запустил его со старой версией моего ASIHTTPFormRequest. Он все еще работает так. Проблема, безусловно, в реализации AFNetworking. –

ответ

0

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

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

Несколько моментов:

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

Я скорректировал приведенный выше код, чтобы быть последним. Проверено, работает ли PHP. Я пытаюсь выполнить блок завершения, но он не позволит мне выполнить log.responsString. Что я должен положить в блок вместо этого? –

+0

Ach! Я получил блок завершения работы. Это дает мне «Nope», что означает, что они, по крайней мере, общаются друг с другом. Но я получаю ответ 400. Таким образом, код говорит, что либо $ _FILES пуст, либо $ _POST ['name'] не установлен. Я также добавил в @ "name" appendPartWithFormData. Вы можете видеть выше всех последних из них. Так что данные этой формы еще не отправляются. –

+0

После обновления до 2.0 нет AFHTTPClient, и с использованием кода Игоря Федорчука появляется предупреждение, любой новый apis? – jeswang

0

У меня есть обходной путь, используя 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]; 
13

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

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]; 
+0

Но если есть способ использовать его без предупреждения? – jeswang