EDIT: Ok, I just set the content-type header to multipart/form-data with no difference. My original question is below:
This is my first question on stack overflow, I hope I'm doing it right.
I am only learning Objective-C, having recently completed the online version of the Stanford course. I know virtually nothing about php and html. The php script and the html I am using are mostly copied off a tutorial. Obj-C makes more sense to me.
The problem:
I have a php script. It uploads an image file. It works properly when called from an html file in the same folder on the server. I am trying to get the same script to work when it is called from my obj-c. It seems to run, it returns 200, the obj-c does call the php, but no file appears in the online folder.
There seems to be very little about this on the web since it was only introduced in ios7. No examples I have found deal with file upload, they all deal with download and merely say that upload is similar. What I have done seems to satisfy any tutorials I have found.
What I know is:
- the php works, and the file is uploaded, when it is called form the html file on the server
- the obj-c is definitely calling the php script (I wrote some logging (using file_put_contents) into the php which confirms that the script is being called when I run the obj-c)
- the obj-c is pretty much definitely uploading the image file (if I use a delegate method in the obj-c it shows upload progress)
- but the php script is not receiving the file (the logging I wrote into the php shows that $_FILES has no value, when called from the obj-c. When called from html it works as expected)
- I just edited the php to log the headers it receives, and it does get the Content-Length of the image file.
Things that may be important:
- I am not adding any html headers, no tutorials that I have seen say that I have to (with NSURLSessionUploadTask), I assume NSURLSessionUploadTask sorts this out for you? Or is this my problem?
- the [response description] returns a 200, quote: { URL: (the PHP script URL) } { status code: 200, headers { Connection = "Keep-Alive"; "Content-Type" = "text/html"; Date = "Thu, 16 Jan 2014 19:58:10 GMT"; "Keep-Alive" = "timeout=5, max=100"; Server = Apache; "Transfer-Encoding" = Identity; } }
- the html specifies enctype="multipart/form-data", perhaps this has to be worked into my obj-c somewhere?
- I am only running it off the simulator so far
- any help will be immensely appreciated! thanks :)
- edit, I just edited the below code to show [request setHTTPMethod:@"POST"] instead of [request setHTTPMethod:@"PUSH"] that I originally had, but it makes no change.
Here is the objective C
- (void) uploadFile: (NSURL*) localURL toRemoteURL: (NSURL*) phpScriptURL
{
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:phpScriptURL];
[request setHTTPMethod:@"POST"];
NSURLSessionUploadTask* uploadTask = [defaultSession uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
if (error == nil)
{
NSLog(@"NSURLresponse =%@", [response description]);
// do something !!!
} else
{
//handle error
}
[defaultSession invalidateAndCancel];
}];
self.imageView.image = [UIImage imageWithContentsOfFile:localURL.path]; //to confirm localURL is correct
[uploadTask resume];
}
and here is the PHP script that is on the server
<?php
$file = 'log.txt';
$current = file_get_contents($file);
$current .= $_FILES["file"]["name"]." is being uploaded. "; //should write the name of the file to log.txt
file_put_contents($file, $current);
ini_set('display_errors',1);
error_reporting(E_ALL);
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
//&& ($_FILES["file"]["size"] < 100000) //commented out for error checking
&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br>";
echo "Type: " . $_FILES["file"]["type"] . "<br>";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
if (move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $_FILES["file"]["name"]))
{
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
else
{
echo "Error saving to: " . "upload/" . $_FILES["file"]["name"];
}
}
}
}
else
{
echo "Invalid file";
}
?>
and here is the html file that works as expected when calling the same script
<html>
<body>
<form action="ios_upload.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>