file upload到iPhone编程中的HTTP服务器

任何人都可以提供一些链接或示例来使用iPhone API将file upload到HTTP服务器。

感谢提前,BP

下面的代码使用HTTP POST将NSData发布到Web服务器。 您还需要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是networkingAPI的一个很好的包装,使得上传文件变得非常简单。 这里是他们的例子(但你也可以在iPhone上做这个 – 我们将图像保存到“磁盘”,然后上传它们。

 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"]; 

我使用ASIHTTPRequest很像Jane Sales的答案,但它不在开发中,作者build议使用其他库,如AFNetworking。

老实说,我想现在是开始寻找其他地方的时候了。

AFNetworking的工作很好,让你用块很多(这是一个很大的安慰)。

以下是在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 <AFMultipartFormData>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]; 

这是一个很好的包装,但是当发布到一个asp.net网页时,需要设置两个额外的post值:

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

试试这个.. 很容易理解和实施…

您可以直接在这里下载示例代码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); } 

这不是一个替代解决scheme; 而是对布兰登广受欢迎的回答(似乎我没有足够的代表评论这个答案)的build议。 如果你正在上传大文件, 你可能会得到一个mmap的mallocexception,因为必须将文件读入内存才能将其发送到服务器。

你可以通过replace来调整Brandon的代码:

 [request setHTTPBody:postbody]; 

附:

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

我以为我会添加一些服务器端PHP代码到这个答案任何初学者阅读这篇文章,并努力弄清楚如何接收服务器端的文件并将文件保存到文件系统。

我意识到这个答案并不直接回答OP的问题,但是由于Brandon的回答对于iOS设备端的上传是足够的,他提到了一些关于php的知识是必要的,我想我会用这个答案来填补php的空白。

这里是一个类,我把一些示例使用代码放在一起。 请注意,这些文件存储在基于哪个用户正在上传文件的目录中。 这可能会或可能不适用于您的使用,但我想我会留在原地以防万一。

 <?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.'); } } ?> 

以下是一些演示如何使用上传类的示例代码。

 // 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); } 

我为github上的Mobile-AppSales应用程序提供了一个轻量级的备份方法

我在这里写了http://memention.com/blog/2009/11/22/Lightweight-backup.html

ReportManager.m查找- (void)startUpload方法

@ Brandon的答案更新,推广到一种方法

 - (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; } } 

像这样调用,从string发送数据:

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