I am trying to upload an image which selected from photo library using AFNetworking but I am little confused. Some code samples are using image data directly for upload and some are using file path. I want to use AFNetworking sample code here:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration
defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];
But I do not know how can I get path of image which I have selected from photo library. Can anyone tell me how can I get path of image which I have selected from photo library?
EDIT 1:
OK! I have found following solution for path:
NSString *path = [NSTemporaryDirectory()
stringByAppendingPathComponent:@"upload-image.tmp"];
NSData *imageData = UIImageJPEGRepresentation(originalImage, 1.0);
[imageData writeToFile:path atomically:YES];
[self uploadMedia:path];
Now am still confused becouse I have created a folder for uploaded images on my server. But how AFNetworking will upload this image to my folder without accessing any service.php page. Just http://example.com/upload is enough? When I try to upload I am getting following error:
Error:
Error Domain=kCFErrorDomainCFNetwork
Code=303 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)"
UserInfo=0x1175a970 {NSErrorFailingURLKey=http://www.olcayertas.com/arendi,
NSErrorFailingURLStringKey=http://www.olcayertas.com/arendi}
EDIT 2:
OK. I have managed to solve error with following code:
-(void)uploadMedia:(NSString*)filePath {
NSURLSessionConfiguration *configuration =
[NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager =
[[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURL *requestURL =
[NSURL URLWithString:@"http://www.olcayertas.com/fileUpload.php"];
NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:requestURL];
[request setHTTPMethod:@"POST"];
NSURL *filePathURL = [NSURL fileURLWithPath:filePath];
NSURLSessionUploadTask *uploadTask =
[manager uploadTaskWithRequest:request
fromFile:filePathURL progress:nil
completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];
}
I am using following PHP code in server side for uploading file:
<?php header('Content-Type: text/plain; charset=utf-8');
try {
// Undefined | Multiple Files | $_FILES Corruption Attack
// If this request falls under any of them, treat it invalid.
if (!isset($_FILES['upfile']['error']) ||
is_array($_FILES['upfile']['error'])) {
throw new RuntimeException('Invalid parameters.');
error_log("File Upload: Invalid parameters.", 3, "php2.log");
}
// Check $_FILES['upfile']['error'] value.
switch ($_FILES['upfile']['error']) {
case UPLOAD_ERR_OK:
break;
case UPLOAD_ERR_NO_FILE:
throw new RuntimeException('No file sent.');
error_log("File Upload: No file sent.", 3, "php2.log");
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
throw new RuntimeException('Exceeded filesize limit.');
error_log("File Upload: Exceeded filesize limit.", 3, "php2.log");
default:
throw new RuntimeException('Unknown errors.');
error_log("File Upload: Unknown errors.", 3, "php2.log");
}
// You should also check filesize here.
if ($_FILES['upfile']['size'] > 1000000) {
throw new RuntimeException('Exceeded filesize limit.');
error_log("File Upload: Exceeded filesize limit.", 3, "php2.log");
}
// DO NOT TRUST $_FILES['upfile']['mime'] VALUE !!
// Check MIME Type by yourself.
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
$finfo->file($_FILES['upfile']['tmp_name']),
array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
), true)) {
throw new RuntimeException('Invalid file format.');
error_log("File Upload: Invalid file format.", 3, "php2.log");
}
// You should name it uniquely.
// DO NOT USE $_FILES['upfile']['name'] WITHOUT ANY VALIDATION !!
// On this example, obtain safe unique name from its binary data.
if (!move_uploaded_file($_FILES['upfile']['tmp_name'], sprintf('./uploads/%s.%s', sha1_file($_FILES['upfile']['tmp_name']), $ext))) {
throw new RuntimeException('Failed to move uploaded file.');
error_log("File Upload: Failed to move uploaded file.", 3, "php2.log");
}
echo 'File is uploaded successfully.';
error_log("File Upload: File is uploaded successfully.", 3, "php2.log");
} catch (RuntimeException $e) {
echo $e->getMessage();
error_log("File Upload: " . $e->getMessage(), 3, "php2.log");
}
?>
EDIT 3:
Now I have learned how $_FILES works. How ever when I run my code I am getting success message but file is not uploading to server. Any idea what might be wrong?
Although there are other ways of uploading an image, if you want to use the method you describe then after selecting an image you can get its URL like this:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];
}
This is assuming you use UIImagePickerController
to select an image.
Afnetworking has a upload method through multipart post.
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/v1/api" parameters:parameters constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:imageData name:@"filename" fileName:@"file.jpg" mimeType:@"image/jpeg"];
}];
where imageData is:
UIImage *originalImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImageJPEGRepresentation(originalImage, 1.0);
Use the following code
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *image = info[UIImagePickerControllerOriginalImage];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc]init];
[parameters setObject:@"imageUploaing" forKey:@"firstKey"];
NSString *fileName = [NSString stringWithFormat:@"%ld%c%c.jpg", (long)[[NSDate date] timeIntervalSince1970], arc4random_uniform(26) + 'a', arc4random_uniform(26) + 'a'];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSData *data = UIImageJPEGRepresentation(image, 0.5);
[manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:data name:@"image" fileName:fileName mimeType:@"image/jpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
}