Rest service for Posting comment to document and upload Document as attachment.
Hello Team
I am currently working on native iOS app (using objective c) and I am using documentum rest services. Currently I am able to use get services of documentum for fetching data from Server. But now I need to use post services of Documentum for sending data from iOS Device to Server. Following task I need to achieve using post services of Documentum.
- Adding Comments on documents using post service.
- Uploading Document as Attachment to server using post service.
I had read Previous discussion regarding how to Post data using post services of Documentum but No success yet. Please guide me how can I accomplish this? Or give me lead that I can search and Implement.
Thanks in Advance.
Comments
-
Hi Vishal,
As for your require, here is the sample codes using AFNetworking to consume Rest Service.
//
// ViewController.m
// OCRest
//
// Created by Song, Michyo on 12/5/16.
// Copyright © 2016 EMC. All rights reserved.
//
#import "ViewController.h"
#import "AFNetworking.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Sample Code for adding Comments
NSDictionary *params = @{ @city : @""};
NSString *url = @""; // Please replace with your own url posted to, eg. http://localhost:8080/repositories/REPO/objects/1/comments
[self postRequest: url params: params];
// Sample Code for uploading document as multipart
NSString *filePath = @""; // Plase replace with your own file path.
NSString *multiPartUrl = @""; // Please replace with your own url posted to, eg. http://localhost:8080/repositories/REPO/objects/1
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSData *data = [[NSFileManager defaultManager] contentsAtPath:filePath];
NSString *fileName = @""; // Plase replace with your own file name.
[self postMultipart :multiPartUrl fileName: fileName file: data progress:nil params:nil]; // There is no UI here, you can point this Progress View to your own one.
}
else
{
NSLog(@File not exits);
}
}
// MARK: - Helper functions
- (void)postRequest: (NSString*) url params:(NSDictionary*) parametersDictionary {
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@application/json forHTTPHeaderField:@Content-Type];
[manager
POST:url parameters:parametersDictionary
progress:nil // You can set here if you need it do in progress
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@success!); // Do for after success
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@error: %@", error); // Do for catch failure
}];
}
- (void)postMultipart: (NSString*) url fileName: (NSString*)name file:(NSData*) fileData progress:(UIProgressView*) progressView params:(NSDictionary*) parametersDictionary {
NSDictionary *meta = @{@propreties: @{@object_name: name}}; // You can modify this part to add more detail.
NSData *metaData = [NSKeyedArchiver archivedDataWithRootObject:meta];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@POST URLString: url parameters: parametersDictionary constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:metaData name:@metadata fileName:@metadata mimeType:@application/vnd.emc.documentum+json];
[formData appendPartWithFileData:fileData name:@binary fileName:name mimeType:@text/plain]; // Your file to upload
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask; // Create resumable task
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress:uploadProgress.fractionCompleted]; //Update the progress view
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@Error: %@", error);
} else {
NSLog(@%@ %@", response, responseObject);
}
}];
[uploadTask resume];
}
@endWhat's more, REST team is now working on iOS application sample for customers in Swift and also have one legacy in Objective-C. In future, there may come iOS framework in Swift.
Since iOS is moving to Swift, we recommend using Swift for iOS development so that we can support better.
May you have any question, please feel free to leave message here and we will do our best to support.
Thank you.
0 -
Thanks Michyo SONG for your quick reply and Help. One more question, For uploading document to server Which path you had selected for selecting document means is it from Application's Document Directory or iCloud saved document?
0 -
Hi Visha1,
As mentioned in my previous code snippet, the following codes can help you get a document on your device with a full file path.
[[NSFileManager defaultManager] fileExistsAtPath:filePath]If you want to get access to your Application's Document Directory, you can use NSBundle to help get paths.
Since I have not yet communicated with iCloud, I am not very familiar with this technology. After searching online, I found this iClouddocumentSync library may help you solve this problem. Please go to its page to see if it can help.
For your question to William about comments, here is the tutorial for commenting with REST service. You may find your answer here.
PS: If this a new application created for your organization, we recommend Swift rather than Objective-C so that you can get better support.
0 -
Hi Michyo SONG
As per your given Code Snippet I had tried to upload Document to server using AFNetworking. But it did Not work. I had use following code to upload document and I had got the Error. Please help me to solve this issue.
My Code:
- (IBAction)btnPostDocumentToServer:(id)sender {
NSString *authStr = [NSString stringWithFormat:@%@:%@",[[NSUserDefaults standardUserDefaults] stringForKey:@username],[[NSUserDefaults standardUserDefaults] stringForKey:@password]];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:@Basic %@", [authData base64Encoding]];
NSDictionary *headers = @{ @content-type: @multipart/form-data; boundary=---011000010111000001101001,
@authorization: authValue,
@postman-token: @6e3d3d97-0ca2-db81-844d-56d6fd72e4ac };
NSData *pdfData = [NSData dataWithContentsOfFile:path];
[self postMultipart:@"http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f" fileName:@temCodeiOS file:pdfData progress:nil params:headers];
}
- (void)postMultipart: (NSString*) url fileName: (NSString*)name file:(NSData*) fileData progress:(UIProgressView*) progressView params:(NSDictionary*) parametersDictionary {
NSDictionary *meta = @{@properties:@{@r_object_type: @ecr_attachment, @document_id: @0903445d80210726,@object_name: @temCodeiOS.pdf,@a_content_type:@pdf,@subject:@new Doc from iOS Device}}; //@{@propreties: @{@object_name: name}}; // You can modify this part to add more detail.
NSData *metaData = [NSKeyedArchiver archivedDataWithRootObject:meta];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@POST URLString: url parameters: parametersDictionary constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:metaData name:@metadata fileName:@metadata mimeType:@application/json];//@application/vnd.emc.documentum+json
[formData appendPartWithFileData:fileData name:@binary fileName:name mimeType:@text/plain]; // Your file to upload
} error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask; // Create resumable task
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress:uploadProgress.fractionCompleted]; //Update the progress view
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@Error: %@", error);
} else {
NSLog(@%@ %@", response, responseObject);
}
}];
[uploadTask resume];
}
Error:
Error: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: unauthorized (401)" UserInfo={NSUnderlyingError=0x60800044ae00 {Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: application/vnd.emc.documentum+json" UserInfo={com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x60000042d900> { URL: http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f } { status code: 401, headers {
"Content-Type" = "application/vnd.emc.documentum+json;charset=UTF-8";
Date = "Tue, 13 Dec 2016 06:36:29 GMT";
Server = "Apache-Coyote/1.1";
"Transfer-Encoding" = Identity;
"Www-Authenticate" = "Basic realm=\"com.emc.documentum.rest\"";
} }, NSErrorFailingURLKey=http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f, com.alamofire.serialization.response.error.data=<7b227374 61747573 223a3430 312c2263 6f646522 3a22455f 47454e45 52414c5f 41555448 454e5449 43415449 4f4e5f45 52524f52 222c226d 65737361 6765223a 22417574 68656e74 69636174 696f6e20 6661696c 65642e22 2c226465 7461696c 73223a22 46756c6c 20617574 68656e74 69636174 696f6e20 69732072 65717569 72656420 746f2061 63636573 73207468 69732072 65736f75 72636522 7d>, NSLocalizedDescription=Request failed: unacceptable content-type: application/vnd.emc.documentum+json}}, com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x60000042d900> { URL: http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f } { status code: 401, headers {
"Content-Type" = "application/vnd.emc.documentum+json;charset=UTF-8";
Date = "Tue, 13 Dec 2016 06:36:29 GMT";
Server = "Apache-Coyote/1.1";
"Transfer-Encoding" = Identity;
"Www-Authenticate" = "Basic realm=\"com.emc.documentum.rest\"";
} }, NSErrorFailingURLKey=http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f, com.alamofire.serialization.response.error.data=<7b227374 61747573 223a3430 312c2263 6f646522 3a22455f 47454e45 52414c5f 41555448 454e5449 43415449 4f4e5f45 52524f52 222c226d 65737361 6765223a 22417574 68656e74 69636174 696f6e20 6661696c 65642e22 2c226465 7461696c 73223a22 46756c6c 20617574 68656e74 69636174 696f6e20 69732072 65717569 72656420 746f2061 63636573 73207468 69732072 65736f75 72636522 7d>, NSLocalizedDescription=Request failed: unauthorized (401)}
0 -
Hi Vishal,
This error message is telling you that your authentication is failed.
The main cause is that the server did not received the correct headers since you may misunderstanding params with headers. Please refer to AFNetworking's official manual. There is a particular part for "Creating an upload task for a multi-part request, with progress". The params in the function would be pass as request body for request not headers as you thought.
The correct passing headers should like:
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@dmadmin password:@password];
NSMutableURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@POST URLString: url parameters: parametersDictionary...The tail is omitted to save space.
The main idea of code above is that you should pass the headers with manager.requestSerializer like the function postRequest showed in example code snippet. And also use the manager.requestSerializer to form your request not initialize a new one.
Additionally, for metadata form data part, since it is defined as JSON format, the raw dictionary should be converted into JSON format and then turned into NSData. Sorry forget to warn you since I have my own converter locally.
Meanwhile, please check your info.plist as this tutorial for detail to enable http request with authentication.
Another point needs to pay attention is the version of Xcode and AFNetworking. While I am using AFNetworking 3.1 and Xcode 7.3 with iOS 9.3, everything runs well. There is a big gap between AFNetworking 3.1 and 2.X. Please check its release note for details.
Finally, since I am also new to iOS for several months and I write Swift for application, I am afraid I could not answer all your question properly. I recommend the ios developer fomular and http://stackoverflow.com for your future questions. Hope they can help you.
Best regards,
Michyo
0 -
Hi Michyo
As per your suggestion I had made changes in code and modify the Headers, for your info I'm using Xcode 8.1 iOS 10.1 simulator and AFNetwoking 3.0 version. But still i had same issue. Actually I did not use AFNetwroking Library before as I'm prefer to write my own request methods using NSURLSession Class. Its OK if you cannot answer my question properly Your hint and Little help will be valuable and sufficient. Thanks For all your Valuable Support till now.
My Modified code is following, I had made changes in header, please check and tell me where I am going wrong.
Code:
- (IBAction)btnPostDocumentToServer:(id)sender {
NSString *filePath=[[NSBundle mainBundle] pathForResource:@demotpcode ofType:@pdf];
NSData *pdfData = [NSData dataWithContentsOfFile:filePath];
[self postMultipart:@"http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f" fileName:@temCodeiOS file:pdfData progress:nil params:nil];
}
- (void)postMultipart: (NSString*) url fileName: (NSString*)name file:(NSData*) fileData progress:(UIProgressView*) progressView params:(NSDictionary*) parametersDictionary {
NSDictionary *meta = @{@properties:@{@r_object_type: @ecr_attachment, @document_id: @0903445d80210726,@object_name: @temCodeiOS.pdf,@a_content_type:@pdf,@subject:@new Doc from iOS Device}}; //@{@propreties: @{@object_name: name}}; // You can modify this part to add more detail.
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:[[NSUserDefaults standardUserDefaults] stringForKey:@username] password:[[NSUserDefaults standardUserDefaults] stringForKey:@password]];
NSMutableURLRequest *request=[manager.requestSerializer multipartFormRequestWithMethod:@POST URLString:url parameters:parametersDictionary constructingBodyWithBlock:^(id<AFMultipartFormData> formData){
[formData appendPartWithFileData:metaData name:@metaData fileName:@metaData mimeType:@application/json];
[formData appendPartWithFileData:fileData name:@binary fileName:name mimeType:@text/plain];
} error:nil];
NSURLSessionUploadTask *uploadTask; // Create resumable task
uploadTask = [manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress:uploadProgress.fractionCompleted]; //Update the progress view
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@Error: %@", error);
} else {
NSLog(@%@ %@", response, responseObject);
}
}];
[uploadTask resume];
}
ERROR:
Error: Error Domain=com.alamofire.error.serialization.response Code=-1011 "Request failed: bad request (400)" UserInfo={NSUnderlyingError=0x600000056350 {Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: application/vnd.emc.documentum+json" UserInfo={com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x6080004318c0> { URL: http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f } { status code: 400, headers {
Connection = close;
"Content-Type" = "application/vnd.emc.documentum+json;charset=UTF-8";
Date = "Thu, 15 Dec 2016 06:46:20 GMT";
Server = "Apache-Coyote/1.1";
"Transfer-Encoding" = Identity;
} }, NSErrorFailingURLKey=http://devser1:9090/dctm-rest/repositories/TPMobile/folders/0b03445d800bfa1f, com.alamofire.serialization.response.error.data=<7b227374 61747573……
0 -
-
Hi Vishal,
For your code, an obvious problem is the format of request headers. I have mentioned in last comment:
Additionally, for metadata form data part, since it is defined as JSON format, the raw dictionary should be converted into JSON format and then turned into NSData. Sorry forget to warn you since I have my own converter locally.Please notice that you should announce in the formdata part about meta data should in format of "application/json+vnd.emc.documentum". Hence, you should provide JSON format metadata other than RAW NSDictionary.
For transforming JSON, you can try for this kind of JSONKit or any other library you like. Please refer to its manual for details.
One more advice, since your error code is 400 for bad request, it will be helpful to open DEBUG mode of Rest Service and find out detail error messages. You can use breakpoint to dig out true reason for your failure.
Wish you can solve this problem ASAP.
Best regards,
Michyo
0
Categories
- All Categories
- 123 Developer Announcements
- 54 Articles
- 151 General Questions
- 148 Thrust Services
- 57 OpenText Hackathon
- 37 Developer Tools
- 20.6K Analytics
- 4.2K AppWorks
- 9K Extended ECM
- 918 Core Messaging
- 84 Digital Asset Management
- 9.4K Documentum
- 32 eDOCS
- 186 Exstream
- 39.8K TeamSite
- 1.7K Web Experience Management
- 8 XM Fax
- Follow Categories