Carga de archivos al servidor HTTP en la progtwigción de iphone

¿Alguien puede proporcionarme algunos enlaces o ejemplos para cargar archivos al servidor HTTP utilizando las API de iPhone?

El siguiente código utiliza HTTP POST para publicar NSData en un servidor web. También necesitas un conocimiento menor de PHP.

NSString *urlString = @"http://yourserver.com/upload.php"; NSString *filename = @"filename"; request= [[[NSMutableURLRequest alloc] init] autorelease]; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; NSString *boundary = @"---------------------------14737809831466499882746641449"; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; NSMutableData *postbody = [NSMutableData data]; [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@.jpg\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[NSData dataWithData:YOUR_NSDATA_HERE]]; [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:postbody]; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; NSLog(@"%@", returnString); 

ASIHTTPRequest es una gran envoltura alrededor de las API de la red y hace que sea muy fácil cargar un archivo. Aquí está su ejemplo (pero también puedes hacerlo en el iPhone; guardamos las imágenes en “disco” y luego las cargamos).

 ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease]; [request setPostValue:@"Ben" forKey:@"first_name"]; [request setPostValue:@"Copsey" forKey:@"last_name"]; [request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"]; 

Utilicé ASIHTTPRequest mucho como la respuesta de Jane Sales pero ya no está en desarrollo y el autor sugiere usar otras bibliotecas como AFNetworking.

Honestamente, creo que ahora es el momento de empezar a buscar en otro lado.

AFNetworking funciona muy bien y te permite trabajar mucho con bloques (lo que es un gran alivio).

Aquí hay un ejemplo de carga de imagen desde su página de documentación en github :

 NSURL *url = [NSURL URLWithString:@"http://api-base-url.com"]; AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"avatar.jpg"], 0.5); NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id formData) { [formData appendPartWithFileData:imageData name:@"avatar" fileName:@"avatar.jpg" mimeType:@"image/jpeg"]; }]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite); }]; [httpClient enqueueHTTPRequestOperation:operation]; 

Esta es una gran envoltura, pero cuando se publica en una página web de asp.net , se deben establecer dos valores de publicación adicionales:

  ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; //ADD THESE, BECAUSE ASP.NET is Expecting them for validation //Even if they are empty you will be able to post the file [request setPostValue:@"" forKey:@"__VIEWSTATE"]; [request setPostValue:@"" forKey:@"__EVENTVALIDATION"]; /// [request setFile:FIleName forKey:@"fileupload_control_Name"]; [request startSynchronous]; 

Prueba esto … muy fácil de entender e implementar …

Puede descargar el código de muestra directamente aquí https://github.com/Tech-Dev-Mobile/Json-Sample

 - (void)simpleJsonParsingPostMetod { #warning set webservice url and parse POST method in JSON //-- Temp Initialized variables NSString *first_name; NSString *image_name; NSData *imageData; //-- Convert string into URL NSString *urlString = [NSString stringWithFormat:@"demo.com/your_server_db_name/service/link"]; NSMutableURLRequest *request =[[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; NSString *boundary = @"14737809831466499882746641449"; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; //-- Append data into posr url using following method NSMutableData *body = [NSMutableData data]; //-- For Sending text //-- "firstname" is keyword form service //-- "first_name" is the text which we have to send [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",@"firstname"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"%@",first_name] dataUsingEncoding:NSUTF8StringEncoding]]; //-- For sending image into service if needed (send image as imagedata) //-- "image_name" is file name of the image (we can set custom name) [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition:form-data; name=\"file\"; filename=\"%@\"\r\n",image_name] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[NSData dataWithData:imageData]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; //-- Sending data into server through URL [request setHTTPBody:body]; //-- Getting response form server NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; //-- JSON Parsing with response data NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil]; NSLog(@"Result = %@",result); } 

Esta no es una solución alternativa; más bien una sugerencia para la respuesta popular de Brandon (viendo como si no tuviera suficiente representante para comentar esa respuesta). Si está cargando archivos de gran tamaño; es probable que obtenga una excepción de mmap malloc por tener que leer el archivo en la memoria para publicarlo en su servidor.

Puede modificar el código de Brandon reemplazando:

 [request setHTTPBody:postbody]; 

Con:

 NSInputStream *stream = [[NSInputStream alloc] initWithData:postbody]; [request setHTTPBodyStream:stream]; 

Pensé en agregar algún código de php del lado del servidor a esta respuesta para los principiantes que lean esta publicación y tengan dificultades para descubrir cómo recibir el archivo en el lado del servidor y guardar el archivo en el sistema de archivos.

Me doy cuenta de que esta respuesta no responde directamente a la pregunta del OP, pero como la respuesta de Brandon es suficiente para el lado del dispositivo iOS de carga y menciona que es necesario cierto conocimiento de php, pensé que llenaría la brecha php con esta respuesta.

Aquí hay una clase que reuní junto con algún código de uso de muestra. Tenga en cuenta que los archivos se almacenan en directorios según el usuario que los está cargando. Esto puede o no ser aplicable a su uso, pero pensé que lo dejaría en su lugar por si acaso.

 < ?php class upload { protected $user; protected $isImage; protected $isMovie; protected $file; protected $uploadFilename; protected $uploadDirectory; protected $fileSize; protected $fileTmpName; protected $fileType; protected $fileExtension; protected $saveFilePath; protected $allowedExtensions; function __construct($file, $userPointer) { // set the file we're uploading $this->file = $file; // if this is tied to a user, link the user account here $this->user = $userPointer; // set default bool values to false since we don't know what file type is being uploaded yet $this->isImage = FALSE; $this->isMovie = FALSE; // setup file properties if (isset($this->file) && !empty($this->file)) { $this->uploadFilename = $this->file['file']['name']; $this->fileSize = $this->file['file']['size']; $this->fileTmpName = $this->file['file']['tmp_name']; $this->fileType = $this->file['file']['type']; } else { throw new Exception('Received empty data. No file found to upload.'); } // get the file extension of the file we're trying to upload $tmp = explode('.', $this->uploadFilename); $this->fileExtension = strtolower(end($tmp)); } public function image($postParams) { // set default error alert (or whatever you want to return if error) $retVal = array('alert' => '115'); // set our bool $this->isImage = TRUE; // set our type limits $this->allowedExtensions = array("png"); // setup destination directory path (without filename yet) $this->uploadDirectory = DIR_IMG_UPLOADS.$this->user->uid."/photos/"; // if user is not subscribed they are allowed only one image, clear their folder here if ($this->user->isSubscribed() == FALSE) { $this->clearFolder($this->uploadDirectory); } // try to upload the file $success = $this->startUpload(); if ($success === TRUE) { // return the image name (NOTE: this wipes the error alert set above) $retVal = array( 'imageName' => $this->uploadFilename, ); } return $retVal; } public function movie($data) { // update php settings to handle larger uploads set_time_limit(300); // you may need to increase allowed filesize as well if your server is not set with a high enough limit // set default return value (error code for upload failed) $retVal = array('alert' => '92'); // set our bool $this->isMovie = TRUE; // set our allowed movie types $this->allowedExtensions = array("mov", "mp4", "mpv", "3gp"); // setup destination path $this->uploadDirectory = DIR_IMG_UPLOADS.$this->user->uid."/movies/"; // only upload the movie if the user is a subscriber if ($this->user->isSubscribed()) { // try to upload the file $success = $this->startUpload(); if ($success === TRUE) { // file uploaded so set the new retval $retVal = array('movieName' => $this->uploadFilename); } } else { // return an error code so user knows this is a limited access feature $retVal = array('alert' => '13'); } return $retVal; } //------------------------------------------------------------------------------- // Upload Process Methods //------------------------------------------------------------------------------- private function startUpload() { // see if there are any errors $this->checkForUploadErrors(); // validate the type received is correct $this->checkFileExtension(); // check the filesize $this->checkFileSize(); // create the directory for the user if it does not exist $this->createUserDirectoryIfNotExists(); // generate a local file name $this->createLocalFileName(); // verify that the file is an uploaded file $this->verifyIsUploadedFile(); // save the image to the appropriate folder $success = $this->saveFileToDisk(); // return TRUE/FALSE return $success; } private function checkForUploadErrors() { if ($this->file['file']['error'] != 0) { throw new Exception($this->file['file']['error']); } } private function checkFileExtension() { if ($this->isImage) { // check if we are in fact uploading a png image, if not return error if (!(in_array($this->fileExtension, $this->allowedExtensions)) || $this->fileType != 'image/png' || exif_imagetype($this->fileTmpName) != IMAGETYPE_PNG) { throw new Exception('Unsupported image type. The image must be of type png.'); } } else if ($this->isMovie) { // check if we are in fact uploading an accepted movie type if (!(in_array($this->fileExtension, $this->allowedExtensions)) || $this->fileType != 'video/mov') { throw new Exception('Unsupported movie type. Accepted movie types are .mov, .mp4, .mpv, or .3gp'); } } } private function checkFileSize() { if ($this->isImage) { if($this->fileSize > TenMB) { throw new Exception('The image filesize must be under 10MB.'); } } else if ($this->isMovie) { if($this->fileSize > TwentyFiveMB) { throw new Exception('The movie filesize must be under 25MB.'); } } } private function createUserDirectoryIfNotExists() { if (!file_exists($this->uploadDirectory)) { mkdir($this->uploadDirectory, 0755, true); } else { if ($this->isMovie) { // clear any prior uploads from the directory (only one movie file per user) $this->clearFolder($this->uploadDirectory); } } } private function createLocalFileName() { $now = time(); // try to create a unique filename for this users file while(file_exists($this->uploadFilename = $now.'-'.$this->uid.'.'.$this->fileExtension)) { $now++; } // create our full file save path $this->saveFilePath = $this->uploadDirectory.$this->uploadFilename; } private function clearFolder($path) { if(is_file($path)) { // if there's already a file with this name clear it first return @unlink($path); } elseif(is_dir($path)) { // if it's a directory, clear it's contents $scan = glob(rtrim($path,'/').'/*'); foreach($scan as $index=>$npath) { $this->clearFolder($npath); @rmdir($npath); } } } private function verifyIsUploadedFile() { if (! is_uploaded_file($this->file['file']['tmp_name'])) { throw new Exception('The file failed to upload.'); } } private function saveFileToDisk() { if (move_uploaded_file($this->file['file']['tmp_name'], $this->saveFilePath)) { return TRUE; } throw new Exception('File failed to upload. Please retry.'); } } ?> 

Aquí hay un código de muestra que demuestra cómo puede usar la clase de carga …

 // get a reference to your user object if applicable $myUser = $this->someMethodThatFetchesUserWithId($myUserId); // get reference to file to upload $myFile = isset($_FILES) ? $_FILES : NULL; // use try catch to return an error for any exceptions thrown in the upload script try { // create and setup upload class $upload = new upload($myFile, $myUser); // trigger file upload $data = $upload->image(); // if uploading an image $data = $upload->movie(); // if uploading movie // return any status messages as json string echo json_encode($data); } catch (Exception $exception) { $retData = array( 'status' => 'FALSE', 'payload' => array( 'errorMsg' => $exception->getMessage() ), ); echo json_encode($retData); } 

He hecho un método de copia de seguridad ligero para la aplicación Mobile-AppSales disponible en github

Escribí sobre esto aquí http://memention.com/blog/2009/11/22/Lightweight-backup.html

Busque el método - (void)startUpload en ReportManager.m

Una actualización de la respuesta de @ Brandon, generalizada a un método

 - (NSString*) postToUrl:(NSString*)urlString data:(NSData*)dataToSend withFilename:(NSString*)filename { NSMutableURLRequest *request= [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; NSString *boundary = @"---------------------------14737809831466499882746641449"; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; NSMutableData *postbody = [NSMutableData data]; [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[NSData dataWithData:dataToSend]]; [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:postbody]; NSError* error; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error]; if (returnData) { return [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; } else { return nil; } } 

Invoque así, enviando datos de una cadena:

 [self postToUrl:@"< #Your url string#>" data:[@"< #Your string to send#>" dataUsingEncoding:NSUTF8StringEncoding] withFilename:@"< #Filename to post with#>"];