2011-12-19 20 views
10

No puedo entender por qué esto no funciona cuando uso AFNetworking. Funcionó con ASIHTTP. Todo esto es muy nuevo para mi. Pero no puedo entender por qué los archivos ya no se transfieren de $ _FILES a la HD del servidor. Aquí está el código IOS:POST Carga jpeg con 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];  



} 

Solía ​​hacer esto:

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

aquí es mi 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

Algunos comentarios: usted debe usar 'vacío ($ _ FILES)' en lugar de 'isset ($ _ FILES)' & '$ _FILES ['filename'] ['tmp_name']' devolverá la ruta completa al archivo cargado, por lo que move_uploaded_file no funcionaría, si agrega 'error_reporting (E_ALL)' a la parte superior de su archivo php, entonces vería el error ... –

+0

¡Gracias! Seguí adelante e hice el cambio de isset a! Empty. Y activó error_reporting. Pero esto es de mi iPhone al servidor. No sé dónde debería ver los errores. Y con respecto a la sintaxis move_uploaded_files, lo saqué directamente del manual php http://php.net/manual/en/function.move-uploaded-file.php. –

+0

Arreglé el código php y lo ejecuté con la versión ASIHTTPFormRequest anterior de mi aplicación. Todavía funciona así. El problema está definitivamente en la implementación de AFNetworking aquí. –

Respuesta

0

No estoy muy familiarizado con lo ASI está haciendo con setPostValue:forKey:, pero es posible que le falte un parámetro name que se enviará por separado de la carga de la imagen.

¿Qué registra el cliente o el servidor, exactamente? Es el registro de bloque de progreso?

Algunos otros puntos:

  • Sólo puede hacer [operation start] al final; no es necesario crear una cola de operaciones solo por eso.
  • Para ayudar con el registro, establezca completionBlock en operation, con NSLog de la respuesta, o algo por el estilo.
  • Es posible que desee crear una clase base AFHTTPClient con un método de clase para devolver una instancia singleton, como el cliente Gowalla API en la aplicación de ejemplo AFNetworking. Ese cliente puede administrar una única cola de operaciones para todas sus solicitudes de red.
+0

He ajustado el código anterior para que sea el más reciente. Verificó que el PHP funciona. Estoy intentando hacer el bloque de finalización, pero no me permitirá registrar operation.responsString. ¿Qué debería poner en el bloque en su lugar? –

+0

Ach! Tengo el bloque de finalización para trabajar. Me está dando "No", lo que significa que al menos se están comunicando entre sí. Pero obtengo una respuesta de 400. Entonces, el código dice que $ _FILES está vacío o $ _POST ['nombre'] no está configurado. También agregué el @ "nombre" appendPartWithFormData. Puede ver, sobre todo, el más reciente de ambos. Por lo tanto, estos datos del formulario no se envían correctamente aún. –

+0

Después de actualizar a 2.0, no hay AFHTTPClient y el uso del código de Igor Fedorchuk recibe una advertencia, ¿alguna nueva apis? – jeswang

0

Tengo una solución utilizando 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

probar este fragmento de código:

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

¿Pero si hay alguna forma de usarlo sin previo aviso? – jeswang