I want to upload video to web service along with some other parameters. I want to upload userID, videoID and video to web service. While uploading, all the parameters other than video is being sent to web service. I've checked at web service end, and the video is not coming with the request. I am using the following code.
- (void)uploadVideoAtLocalPath:(NSString *)videoPath videoID:(NSString *)videoID userID:(NSString *)userID {
NSString *strServerURL = #"www.mysite.com/user/uploadVideo";
NSURL *URL = [NSURL URLWithString:strServerURL];
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:URL];
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST" path:#"" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
// userID
NSData *userIDData = [userID dataUsingEncoding:NSUTF8StringEncoding];
[formData appendPartWithFormData:userIDData name:#"userID"];
// videoID
NSData *videoIDData = [videoID dataUsingEncoding:NSUTF8StringEncoding];
[formData appendPartWithFormData:videoIDData name:#"videoID"];
// video
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoPath]];
[formData appendPartWithFileData:videoData name:#"video" fileName:#"video.mov" mimeType:#"video/quicktime"];
}];
[request setURL:URL];
[request setTimeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[AFHTTPRequestOperation addAcceptableStatusCodes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(100, 500)]];
[operation setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response String: %#", operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", error);
}];
[client enqueueHTTPRequestOperation:operation];
}
Could anyone let me know whether I am doing it correct? If not, could anyone please tell me how to upload video to web service along with other parameters?
Thanks Everyone!
I'm not well in this method. I had the same issue. But, i have fixed it like mixing of POST & GET methods. I just sent my parameters as GET method like below -
NSString *strServerURL = [NSString stringWithFormat:#"www.mysite.com/user/uploadVideo&userID=%d&videoID=%d", 1, 55];
and, sent my video data in POST method as per your method -
NSMutableURLRequest *request = [client multipartFormRequestWithMethod:#"POST" path:#"" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
// video
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:videoPath]];
[formData appendPartWithFileData:videoData name:#"video" fileName:#"video.mov" mimeType:#"video/quicktime"];
}];
You better try to modify your webservice and try like above way. It should works.
Cheers!
Related
I am very new to iOS. I am trying to send data through post method to PHP. In PHP it can't take data like $_POST['data'], but it takes $_GET['data']. My iOS code is as follows.
NSString *strURL = [NSString stringWithFormat:#"http://example.com/app_respond_to_job?emp_id=%#&job_code=%#&status=Worker-Accepted&comment=%#",SaveID2,txtJobcode1,alertTextField.text];
NSURL *apiURL = [NSURL URLWithString:strURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:apiURL];
[urlRequest setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
_receivedData = [[NSMutableData alloc] init];
[connection start];
NSLog(#"URL---%#",strURL);
Can someone explain why is that, it will be very helpful.
Please Download this file https://www.dropbox.com/s/tggf5rru7l3n53m/AFNetworking.zip?dl=0
And import file in your project
Define in #import "AFHTTPRequestOperationManager.h"
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"Your Url"]];
NSDictionary *parameters = #{#"emp_id":SaveID2,#"job_code":txtJobcode1.text,#"status":alertTextField.text};
AFHTTPRequestOperation *op = [manager POST:#"rest.of.url" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[responseObject valueForKey: #"data"];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[op start];
because you send your data via query string in url
i think it will work if you try to pass data in your request's body:[urlRequest setHTTPBody:...]
POST parameters come from the request body, not from the URL string. You'll need to:
Call setHTTPBody on the request and provide the URL-encoded string (sans question mark, IIRC) as the body data
Call setValue:forHTTPHeaderField: to set the Content-Type to application/x-www-form-urlencoded
Either remove the call to [connection start] or use initWithRequest:delegate:startImmediately: so that you aren't starting the connection twice.
That last one is kind of important. You can get strange results if you try to start a connection twice. :-)
I'm trying upload image to server using AFNetworking with PUT request.-
UIImage* snap = info[UIImagePickerControllerOriginalImage];
NSData *imageData = UIImageJPEGRepresentation(snap, 0.3);
NSMutableString * fullPath = [NSMutableString stringWithString:API_BASE_URL];
[fullPath appendFormat:#"%#%#",API_VERSION,req];
NSURL * url = [NSURL URLWithString:fullPath];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
[manager.requestSerializer setValue:[NSString stringWithFormat:#"%#", #kPublicKey] forHTTPHeaderField:#"X-API-KEY"];
[manager.requestSerializer setValue:bodyStr forHTTPHeaderField:#"X-API-DATA"];
NSString *URLString = fullPath;
NSMutableURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:#"PUT" URLString:URLString parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:#"media" fileName:#"upload.jpg" mimeType:#"image/jpeg"];
} error:nil];
AFHTTPRequestOperation *requestOperation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
//success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failure...");
}];
[requestOperation start];
I'm taking image using iPhone camera and upload it to server but it takes too much time to process and images uploaded on server are in huge size(~10-12MB) although i'm trying to compress the image?
What i'm doing wrong?Any suggestion or sample code would be appreciated.
NSData *imageData = UIImageJPEGRepresentation(snap, 1.0);
The second argument in UIImageJPEGRepresentation denotes the compression quality of the image.As per Apple documentation :
compressionQuality :
The quality of the resulting JPEG image, expressed as a value from 0.0 to 1.0. The value 0.0 represents the maximum compression (or lowest quality) while the value 1.0 represents the least compression (or best quality).
Try reducing this to a number which balances the quality of image and speed of upload.
// manager needs to be init'd with a valid baseURL
NSURL *baseURL = [AfarHTTPSessionManager sharedManager].baseURL;
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
NSData *imageData = UIImageJPEGRepresentation(draftHighlight.largeImage, 1);
// need to pass the full URLString instead of just a path like when using 'PUT' or 'POST' convenience methods
NSString *URLString = [NSString stringWithFormat:#"%#%#", baseURL, _the_rest_of_your_path];
NSMutableURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:#"PUT" URLString:URLString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:kCreateHighlightAPIKeyImage fileName:#"highlight_image.jpg" mimeType:#"image/jpeg"];
}];
// 'PUT' and 'POST' convenience methods auto-run, but HTTPRequestOperationWithRequest just
// sets up the request. you're responsible for firing it.
AFHTTPRequestOperation *requestOperation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
// success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// failure
}];
// fire the request
[requestOperation start];
I am trying to upload images to Parse.com using AFNetworking 2.0.
When I download the image which has been stored on 'Parse', then the resulting file is corrupt.
By doing a diff I see that the following data has been appended to the beginning:
There is also appended 'boundry' data at the end of the file.
What am I doing wrong? Mime type?
I send the same file using 'curl' and everything is ok.
This is the code I use for sending:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
[manager.requestSerializer setValue:#"image/jpeg" forHTTPHeaderField:#"Content-Type"];
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
[manager.requestSerializer setValue:value forHTTPHeaderField:key];
}];
[manager POST:#"https://api.parse.com/1/files/imagefile.jpg"
parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
NSData *imgData = UIImageJPEGRepresentation(image, 1.0f);
[formData appendPartWithFileData:imgData
name:#"imagefile"
fileName:#"imagefile.jpg"
mimeType:#"image/jpeg"];
}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
success(operation, responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(operation, error);
}
];
UPDATE
The following code works as expected (not multi-part, so clearly this is the problematic area):
NSMutableString *urlString = [NSMutableString string];
[urlString appendString:#"https://api.parse.com/1/"];
[urlString appendFormat:#"files/imagefile.jpg"];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request addValue:#"***********" forHTTPHeaderField:#"X-Parse-Application-Id"];
[request addValue:#"***********" forHTTPHeaderField:#"X-Parse-REST-API-Key"];
[request addValue:#"image/jpeg" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:UIImageJPEGRepresentation(image, 0.3f)];
NSURLResponse *response = nil;
NSError *error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSString *fileUrl = [httpResponse allHeaderFields][#"Location"];
I tried below code to upload video with Multi part form POST in AFnetworking but when uploading, video sent about 80% is broken. This is my code:
-(void) uploadVideoAPI: (NSString*) emailStr andSumOfFiles: (NSString*) sumSizeFile andVideoNams:(NSMutableArray*) videoNameArr andUpFile :(NSMutableArray *) videoDataArray
{
NSURL *url = [NSURL URLWithString:#"http://myserver.com];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL: url] ;
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:nil parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData) {
[formData appendPartWithFormData:[emailStr dataUsingEncoding:NSUTF8StringEncoding]
name:#"emailStr"]; //parametters1
[formData appendPartWithFormData:[sumSizeFile dataUsingEncoding:NSUTF8StringEncoding] name:#"sumSizeFile"];//parametters 2
for(int i=0;i<[videoDataArray count];i++)
{
NSString * videoName = [videoNameArr objectAtIndex:i];
NSData *videoData = [videoDataArray objectAtIndex:i];
[formData appendPartWithFileData:videoData
name:#"videos"
fileName:videoName mimeType:#"video/quicktime"];
}
}];
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];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Upload Complete");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", operation.responseString);
NSLog(#"%#",error);
}];
[operation start];
}
My code has any problem? Please give me some advice. thanks in advance
I suggest you to use appendPartWithFileURL instead of appendPartWithFormData for files, to avoid memory problems (imagine big data like video or compressed data files).
I use something like this:
// Create request
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:nil parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData) {
// Important!! : file path MUST BE real file path (so -> "file://localhost/.../../file.txt") so i use [NSURL fileURLWithPath:]
NSError* err;
[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePathToUpload] name:[fileInfo objectForKey:#"fileName"] error:&err];
}];
I'm impementing an application in iOS7, it's kind of a social network app with posts with images and a backend that saves all of the data sent form the client. The iOS client is sending the information of the post via json and after the info is sent, it starts to send the image via multipart form using AFNetworking.
I need to be notified when the image is sent, so that I can refresh the main view of the app with the new posts, including the recently posted by the client. In the practice if I request the backend for the last posts and the multipart hasn't finished, the sending of the image gets interruped and fails to send the image.
The backend is develop in WCF and is a RESTful JSON web service.
Here is the method that sends the post to the backend:
+(void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location;
{
NSLog(#"entro a addPost");
NSString *urlBackend = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"URLBackend"];
NSData* dataImage = UIImageJPEGRepresentation(image, 1.0);
NSString* ImageName = [NSString stringWithFormat:#"%#_%#.jpg",idUser ,dateToServer];
NSString *jsonRequest = [NSString stringWithFormat:#"{\"Date\":\"%#\"...."];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#newPost",urlBackend]];
NSMutableURLRequest *request = [ [NSMutableURLRequest alloc] initWithURL:url];
NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:requestData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
if (image != nil) {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:[NSString stringWithFormat:#"%#FileUpload",urlBackend]
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:dataImage name:#"image" fileName:ImageName mimeType:#"image/jpg" ];
}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
}
A couple of thoughts:
You say:
The iOS client is sending the information of the post via json and after the info is sent, it starts to send the image via multipart form using AFNetworking.
Technically, you're not waiting for the information to be sent, but you're doing these concurrently. Do you want these to be concurrent? Or sequential? Or why not just a single request that posts the information as well as the image?
I'd suggest using AFNetworking for both requests. You've got a powerful framework for managing network requests, and it feels awkward to see hairy NSURLConnection code in there.
If you keep the NSURLConnection code in there, note that you do not want to start a NSURLConnection, unless you used initWithRequest:delegate:startImmediately: with NO for that last parameter. You're effectively starting it twice, which can cause problems. I'd suggest removing the start call.
Setting all of that aside, what you want to do is to add a completion block parameter to your method, e.g., something like:
+ (void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location completion:(void (^)(id responseObject, NSError *error))completion
{
// ...
if (image != nil) {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:[NSString stringWithFormat:#"%#FileUpload",urlBackend] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:dataImage name:#"image" fileName:ImageName mimeType:#"image/jpg" ];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (completion) completion(responseObject, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (completion) completion(nil, error);
}];
}
}
You'd then invoke that like so:
[Persistence addPostToServerAddtext:text addimage:image addbeach:nil location:annotation completion:^(id responseObject, NSError *error) {
if (error) {
// handle error
return
}
// otherwise use the responseObject
}];
Now, I don't know what parameters you want to return in your completion block (I'm assuming you wanted to return what the AFHTTPRequestOperationManager did), but just change the parameters for that completion block as suits your needs.
Unrelated to your original question, but I notice that you're building jsonRequest like so:
NSString *jsonRequest = [NSString stringWithFormat:#"{\"Date\":\"%#\"...."];
That's a little risky if any of those fields include user supplied information (e.g. what if the user used double quotes in the information provided). I'd suggest you build a dictionary, and then build the jsonRequest from that. It will be more robust. Thus:
NSDictionary *dictionary = #{#"Date" : date,
#"Message" : message};
NSError *error = nil;
NSData *request = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
if (error)
NSLog(#"%s: dataWithJSONObject error: %#", __FUNCTION__, error);
Or, if you use AFNetworking, I believe it will do this JSON conversion of your dictionary for you. But, bottom line, be very wary about creating JSON strings yourself, at least if the request might include any user supplied information.