2011-12-19 2 views
10

Non riesco a capire perché questo non funzioni quando utilizzo AFNetworking. Ha funzionato con ASIHTTP. Questo è tutto molto nuovo per me. Ma non riesco a capire perché i file non vengano più trasferiti da $ _FILES all'HD del server. Ecco il codice di iOS:Caricamento jpeg POST 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];  



} 

ho usato per fare questo:

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

Ecco il mio 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

Alcuni commenti: si dovrebbe usare 'empty ($ _ FILES)' al posto di 'isset ($ _ FILES)' & '$ _FILES ['filename'] ['tmp_name']' restituirà il percorso completo al file caricato, quindi move_uploaded_file non funzionerebbe, se avessi aggiunto 'error_reporting (E_ALL)' all'inizio del tuo file php allora vedresti l'errore ... –

+0

Grazie! Sono andato avanti e ho fatto il passaggio da isset a! Vuoto. E acceso error_reporting. Ma questo è dal mio iPhone al server. Non so dove dovrei vedere gli errori. E per quanto riguarda la sintassi move_uploaded_files, l'ho estratto direttamente dal manuale php http://php.net/manual/en/function.move-uploaded-file.php. –

+0

Ho corretto il codice php e l'ho eseguito con la vecchia versione ASIHTTPFormRequest della mia app. Funziona ancora così. Il problema è sicuramente nell'implementazione di AFNetworking qui. –

risposta

0

io non sono davvero familiarità con ciò che ASI sta facendo con setPostValue:forKey:, ma potrebbe mancare un parametro name da inviare separatamente dal caricamento dell'immagine.

Che cosa fa esattamente il log del client o del server? La registrazione del blocco di avanzamento?

alcuni altri punti:

  • Si può solo fare [operation start] alla fine; non c'è bisogno di creare una coda di operazioni solo per quello.
  • Per facilitare la registrazione, impostare completionBlock su operation, con un NSLog della risposta o qualcosa del genere.
  • È possibile creare una classe base AFHTTPClient con un metodo di classe per restituire un'istanza singleton, come il client API Gowalla nell'app di esempio AFNetworking. Quel client può quindi gestire una singola coda di operazioni per tutte le richieste di rete.
+0

Ho regolato il codice sopra per essere il più recente. Verificato che il PHP funzioni. Sto provando a fare il blocco di completamento ma non mi permetterà di registrare operation.responsString. Cosa dovrei inserire nel blocco, invece? –

+0

Ach! Ho ottenuto il blocco di completamento per funzionare. Mi sta dando "No", il che significa che stanno almeno comunicando l'uno con l'altro. Ma ricevo una risposta 400. Quindi il codice dice che $ _FILES è vuoto o $ _POST ['nome'] non è impostato. Ho anche aggiunto nel @ "nome" appendPartWithFormData. Puoi vedere soprattutto i più recenti di entrambi. Quindi i dati di questo modulo non vengono ancora inviati correttamente. –

+0

Dopo l'aggiornamento alla 2.0, non c'è AFHTTPClient e usando il codice di Igor Fedorchuk viene visualizzato un avviso, ogni nuova apis? – jeswang

0

Ho una soluzione utilizzando 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

Prova questo frammento di codice:

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

Ma se c'è un modo per usarlo senza preavviso? – jeswang