Is it possible to POST XMLData to the webservices from iPhone OS. The webservices are developed in ASP.net MVC 3.0 with RESTFul url and we would like iPhone developers to send input data in XML format as POST variable..
The webservice actionresult looks like the following where sightings is the parameter that is expected to pass as POST variable
public ActionResult Update(XDocument sightings)
{
try
{
XMLHelper xmlHelper = new XMLHelper();
}
}
That's definitely applicable all you need to do is to use NSMutableURLRequest as the following:
NSString* sXMLToPost = #"<?xml version=\"1.0\"?><Name>user</Name>";
NSData* data = [sXMLToPost dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:#"http://myurl.com/RequestHandler.ashx"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[sXMLToPost dataUsingEncoding:NSUTF8StringEncoding]];
NSURLResponse *response;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
if (error) {
//handle the error
}
And Now in your ASHX file parse the InputStream to read the posted XML:
System.IO.Stream str; String strmContents;
Int32 counter, strLen, strRead;
str = Request.InputStream;
strLen = Convert.ToInt32(str.Length);
byte[] strArr = new byte[strLen];
strRead = str.Read(strArr, 0, strLen);
// Convert byte array to a text string.
strmContents = "";
for (counter = 0; counter < strLen; counter++)
{
strmContents = strmContents + strArr[counter].ToString();
}
Remember you can always check the request type using:
if (context.Request.RequestType == "POST")
MSDN HttpRequest.InputStream
Related
I am trying to post an image to reddit; however, I only kind of know what I am doing. I am using objective c for my iphone app.
Prior to the code listed below I obtain a modhash and cookie by logging in prior to the upload and use NSLog to determine that I truly am receiving them. Then I use a JSON Parser to separate them into separate variables.
I was not sure what all of the POST argument values were supposed to be so I kind of guessed. The necessary arguments are uh, file, formid, header, ing_type, name, and sponsor.
The documentation for reddit api is http://www.reddit.com/dev/api I believe that I want to use the POST /api/upload_sr_img method...
NSURL *url = [NSURL URLWithString:#"http://www.reddit.com/api/upload_sr_img"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *httpBody = [NSString stringWithFormat:#"?uh=%#&file=%#&formid=''header=%#&img_type=%#&name=%#&sponsor=%#",modhash,UIImagePNGRepresentation(self.memeImage.image),#"test",#"png",#"Drew",#"Drew'sApp"];
[request setHTTPBody:[httpBody dataUsingEncoding:NSASCIIStringEncoding]];
NSURLResponse *response = NULL;
NSError *imgError = NULL;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&imgError];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingMutableContainers error:nil];
NSDictionary *responseJson = [json valueForKey:#"json"];
NSLog(#"response is: %#",response);
NSLog(#"imgError is: %#",imgError);
NSLog(#"result is: %#",result);
NSLog(#"json is: %#",json);
NSLog(#"responseJson is: %#",responseJson);
Could use any help I can get.
Also, I was not sure if I needed to send a content-type or even what it would be.
Thanks for your help.
Check this library: https://github.com/MattFoley/MFRedditPostController
You can use the provided UI or create your own.
I have problem in Spring MVC pattern. When i call the web service form iPhone app with encoded value, The decoding is not happening properly. Not sure about what the issue is.
the + sign is getting replaced with a space " ".
Below is my web.xml
<?xml version="1.0" encoding="UTF-8"?><br>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br>
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"<br>
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"<br>
id="WebApp_ID" version="3.0"><br>
<display-name>APPLICATIONNAME</display-name><br>
<filter><br>
<filter-name>encoding-filter</filter-name><br>
<filter-class>org.springframework.web.filter.CharacterEnco dingFilter</filter-class><br>
<init-param><br>
<param-name>encoding</param-name><br>
<param-value>UTF-8</param-value><br>
</init-param><br>
<init-param><br>
<param-name>forceEncoding</param-name><br>
<param-value>true</param-value><br>
</init-param><br>
</filter><br>
<filter-mapping><br>
<filter-name>encoding-filter</filter-name><br>
<url-pattern>/rest/*</url-pattern><br>
</filter-mapping><br>
<servlet><br>
<servlet-name>spring</servlet-name><br>
<servlet-class>org.springframework.web.servlet.DispatcherSe rvlet</servlet-class><br>
<load-on-startup>1</load-on-startup><br>
</servlet><br>
<servlet-mapping><br>
<servlet-name>spring</servlet-name><br>
<url-pattern>/rest/*</url-pattern><br>
</servlet-mapping><br>
<welcome-file-list><br>
<welcome-file>index.jsp</welcome-file><br>
</welcome-file-list><br>
</web-app><br>
My controller class
#Controller
public class LoginController {
#Autowired
private LoginServiceImpl loginService;
#RequestMapping(value = "/getUserDetails", method = RequestMethod.POST)
public #ResponseBody
LoginData getUserDetails(#ModelAttribute LoginDetails loginDetails) {
LOGGER.debug("Session ID = " + loginDetails.getSessionID());
}
Sample input request from iPhone APP
NSURLResponse *response = nil;
NSError *error = nil;
NSString *urlString = #"http://localhost:8080/rest/getUserDetails";
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *connection= [[NSURLConnection alloc] initWithRequest:urlRequest
delegate:self];
[urlRequest setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"sessionID=%#",#"ABCD+/EFGH"];
NSData *a=[postString dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"encoded %#",a);
[urlRequest setHTTPBody:a];
[connection start];
NSString *returnString = [[NSString alloc] initWithData:[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error] encoding:NSUTF8StringEncoding];
NSLog(#" %# ",returnString);
NSLog(#"%#",error);
On the server side instead of "ABCD+/EFGH" i am getting "ABCD /EFGH". SO the plus (+) is not getting decoded.
What needs to be done to get the plus (+) on the server? Any help is appreciated.
It's an expected behavour.
In application/x-www-form-urlencoded form (used for sending form data in POST) space is encoded as +, and real + should be represented in percent-encoded form (%2B).
I think it would be better to use some kind of built-in application/x-www-form-urlencoded encoding routine, if available on iPhone, instead of manual replacement.
i have this in Xcode:
NSString *post =[[NSString alloc] initWithString:#"message";
this string i want to send to myadress.php. anybody help me with some good reference or code please.
this is my php side:
<?
$connect = mysql_connect ("$dbserver", "$dbuser", "$dbpass");
mysql_select_db("$dbname") or die(mysql_error());
$feed = $_GET['feed_message'];
$login = mysql_query("INSERT INTO feedback SET feed_message ='".$feed."'", $connect) or die(mysql_error());
mysql_close($connect);
?>
You can try this and you need implement the NSURLConnection delegate method
NSURL *url = [NSURL URLWithString:#"http://yoururl"];
NSURLRequest *urlReq = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:urlReq delegate:self];
[connection start];
You can also use ASIHttpRequest, it has more Features.
In fact you just want to send a request to specific URL containing parameter "feed_message":
http://myserver.com/myscrypt.php?feed_message=message
To do it you need:
a. Create an url:
NSString * scriptURLString = #"http://myserver.com/myscrypt.php";
NSString * parameterName = #"feed_message";
NSString * post = #"message";
NSString * urlString = [NSString stringWithFormat:#"%#?%#=%#",scriptURLString, parameterName, post];
NSURL * url = [NSURL URLWithString:urlString];
b. send request to url. There are many ways to do it depending on your needs.
You may send asynchronous request (set delegate property and implement delegate methods to handle results)
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url] delegate:nil];
or simply use NSData synchronous method:
[NSData dataWithContentsOfURL:url];
I am attempting to implement an online leaderboard in a game app for iOS, using Django to process POST requests from the iDevice and store the scores. I have figured out how to get Django to serialize the objects to XML, and my iPhone can read and display the scores. However, I can't for the life of me get my iPhone to POST XML to my Django server.
Below is the function I am using to post the scores...
iOS (Objective-C) Controller:
- (void) submitHighScore {
NSLog(#"Submitting high score...");
NSString *urlString = HIGH_SCORES_URL;
NSURL *url = [NSURL URLWithString: urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
[request setHTTPMethod: #"POST"];
[request setValue: #"text/xml" forHTTPHeaderField: #"Content-Type"];
NSMutableData *highScoreData = [NSMutableData data];
[highScoreData appendData: [[NSString stringWithFormat: #"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"<player_name>%#</player_name", #"test"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"<score>%d</score>", 0] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"</xml>"] dataUsingEncoding: NSUTF8StringEncoding]];
[request setHTTPBody: highScoreData];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: request
delegate: self];
if (!connection) {
NSLog(#"Request to send high scores appears to be invalid.");
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
}
}
The above method succeeds in sending the request, and interprets it correctly as CONTENT_TYPE: text/xml, but the Django view that processes the request can't seem to make any sense of it, interpreting it almost as if it was merely plain text. Below is my Django view...
Django (Python) view:
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core import serializers
from django.core.exceptions import ValidationError
from django.views.decorators.csrf import csrf_exempt
from modologger.taptap.models import HighScore
#csrf_exempt
def leaderboard( request, xml = False, template_name = 'apps/taptap/leaderboard.html' ):
"""Returns leaderboard."""
if xml == True: # xml is set as True or False in the URLConf, based on the URL requested
if request.method == 'POST':
postdata = request.POST.copy()
print postdata
# here, postdata is evaluated as:
# <QueryDict: {u'<?xml version': [u'"1.0" encoding="UTF-8" ?><player_name>test</player_name<score>0</score></xml>']}>
for deserialized_object in serializers.deserialize('xml', postdata): # this fails, returning a 500 error
try:
deserialized_object.object.full_clean()
except ValidationError, e:
return HttpResponseBadRequest
deserialized_object.save()
else:
high_score_data = serializers.serialize( 'xml', HighScore.objects.all() )
return HttpResponse( high_score_data, mimetype = 'text/xml' )
else:
high_scores = HighScore.objects.all()
return render_to_response( template_name, locals(), context_instance = RequestContext( request ) )
To be honest, I'm not sure whether the problem lies in the Objective-C or in the Django code. Is the Objective-C not sending the XML in the right format? Or is the Django server not processing that XML correctly?
Any insight would be much appreciated. Thanks in advance.
Update:
I got it to work, by editing the iOS Controller to set the HTTPBody of the request like so:
NSMutableData *highScoreData = [NSMutableData data];
[highScoreData appendData: [[NSString stringWithFormat: #"player_name=%#;", #"test"] dataUsingEncoding: NSUTF8StringEncoding]];
[highScoreData appendData: [[NSString stringWithFormat: #"score=%d", 0] dataUsingEncoding: NSUTF8StringEncoding]];
[request setHTTPBody: highScoreData];
For some reason putting a semicolon in there got Django to recognize it, assign the values to a new instance of a HighScore class, and save it. The logging on the test server indicates request.POST is <QueryDict: {u'score': [u'9'], u'player_name': [u'test']}>.
Still not quite sure what to make of all this.
As per Radu's suggestion, I took a look at highScoreData with NSLog, right after appending it to request.HTTPBody, and the result is <706c6179 65725f6e 616d653d 74657374 3b73636f 72653d39>.
I'm a huge Obj-C noob, so again, any help is appreciated! Thanks again.
Since you control both sides, I'd drop the complexity of xml encoding the data and use RestKit or some other framework that makes it easy to communicate with Django.
Can anyone provide me some links or examples to upload files to the HTTP server using
iphone APIs.
The code below uses HTTP POST to post NSData to a webserver. You also need minor knowledge of 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 is a great wrapper around the network APIs and makes it very easy to upload a file. Here's their example (but you can do this on the iPhone too - we save images to "disk" and later upload them.
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"];
I used ASIHTTPRequest a lot like Jane Sales answer but it is not under development anymore and the author suggests using other libraries like AFNetworking.
Honestly, I think now is the time to start looking elsewhere.
AFNetworking works great, and let you work with blocks a lot (which is a great relief).
Here's an image upload example from their documentation page on 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];
This is a great wrapper, but when posting to a asp.net web page, two additional post values need to be set:
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];
Try this.. very easy to understand & implementation...
You can download sample code directly here 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);
}
This isn't an alternative solution; rather a suggestion for Brandon's popular answer (seeing as though I don't have enough rep to comment on that answer). If you're uploading large files; you're probably going to get a mmap malloc exception on account of having to read the file into memory to post it to your server.
You can tweak Brandon's code by replacing:
[request setHTTPBody:postbody];
With:
NSInputStream *stream = [[NSInputStream alloc] initWithData:postbody];
[request setHTTPBodyStream:stream];
I thought I would add some server side php code to this answer for any beginners that read this post and are struggling to figure out how to receive the file on the server side and save the file to the filesystem.
I realize that this answer does not directly answer the OP's question, but since Brandon's answer is sufficient for the iOS device side of uploading and he mentions that some knowledge of php is necessary, I thought I would fill in the php gap with this answer.
Here is a class I put together with some sample usage code. Note that the files are stored in directories based on which user is uploading them. This may or may not be applicable to your use, but I thought I'd leave it in place just in case.
<?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.');
}
}
?>
Here's some sample code demonstrating how you might use the upload class...
// 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);
}
I have made a lightweight backup method for the Mobile-AppSales app available at github
I wrote about it here http://memention.com/blog/2009/11/22/Lightweight-backup.html
Look for the - (void)startUpload method in ReportManager.m
An update to #Brandon's answer, generalized to a method
- (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;
}
}
Invoke like so, sending data from a string:
[self postToUrl:#"<#Your url string#>"
data:[#"<#Your string to send#>" dataUsingEncoding:NSUTF8StringEncoding]
withFilename:#"<#Filename to post with#>"];