I came into an issue trying to send files with NSURLSessionUploadTask to a custom REST service.
The problem is that the file seems to get transferred up to an arbitrary size, and then the task stops without any error (URLSession:task:didCompleteWithError: gets called with error set to nil).
The file that needs to be transferred is almost 10MB in size, and I found that smaller files sometimes get transferred correctly.
The code I'm using for creating the task is the following:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"100-continue" forHTTPHeaderField:#"Expect"];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d", length] forHTTPHeaderField:#"Content-Length"];
NSURL *fileUrl = [NSURL fileURLWithPath:instanceFilePath];
NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileUrl];
I need to specify some headers for the server to correctly interpret the request, and the length variable is the effective size of the file being sent.
Any idea about what's going on here?
Thanks.
Related
In my application I need to make a PUT type request. I have followed the below steps
NSString *path = #"http://hostname/api/Account/VerifyUser?applicationToken=72B648C6-B2B7-45ED-BA23-2E8AAA187D2C&emailID=xxx#gmail.com&password=aaaaa";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:path]];
[request setHTTPMethod:#"PUT"];
[request setValue:[NSString stringWithFormat:#"%d", string.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded;charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[string dataUsingEncoding:NSUTF8StringEncoding]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
For POST and GET I am getting correct output.
I have searched a lot but i am not getting any solution.Please suggest me any possible solution .
Thanks in advance
Try this
For xml request body
Set [request setValue:#"application/x-www-form-urlencoded;charset=utf-8;application/form-data" forHTTPHeaderField:#"Content-Type"];
OR
For json request body
Set [request setValue:#"application/x-www-form-urlencoded;charset=utf-8;application/json" forHTTPHeaderField:#"Content-Type"];
I need to set up a 30 second time out into my application when it tries to connect a web service. I have tried cachePolicy:timeoutInterval, but that does not have any effect. My code is below:
NSURL *url = [NSURL URLWithString:#"http://myservice.asmx"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMessage length]];
[request addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"http://tempuri.org/GetVehiclesByPhone_ServiceCall_Proc" forHTTPHeaderField:#"SOAPAction"];
[request addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[soapMessage dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]];
NSError *error;
NSURLResponse *response;
webData =[[NSMutableData alloc] init];
webData = (NSMutableData *) [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
Use +[NSURLConnection sendAsynchronousRequest:queue:completionHandler:].
Basically, +[NSURLConnection sendSynchronousRequest:returningResponse:error:] doesn't obey the timeoutInterval that is passed in for small intervals, while, asynchronous requests do.
If you think about how things work, this becomes obvious: synchronous requests are blocking, and, there is no easy way for a watchdog to check for timeouts -- the thread is being blocked!. Asynchronous requests don't block the thread, so, it can check for timeouts every runloop run.
I'm making two calls to my server with different p12 certificates. The problem is that on the second call it is using the certificate from the first call even though I assigned it a new certificate.
First call (it downloads the second certificate I want to use for the second call):
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request addRequestHeader:#"Content-Type" value:#"application/x-pkcs12"];
[request setValidatesSecureCertificate:YES];
[request setCachePolicy: ASIDoNotWriteToCacheCachePolicy | ASIDoNotReadFromCacheCachePolicy];
[request setClientCertificateIdentity:[self copyClientCertificate]];
[request setDownloadDestinationPath:thePath];
[request setDelegate:self];
[request setUseCookiePersistence:YES];
[request startAsynchronous];
[request setDidReceiveResponseHeadersSelector:#selector(didReceiveResponseHeaders:)];
[request setDidFinishSelector:#selector(ConnectFinished:)];
On the second call:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setValidatesSecureCertificate:YES];
[request setCachePolicy: ASIDoNotWriteToCacheCachePolicy | ASIDoNotReadFromCacheCachePolicy];
[request setClientCertificateIdentity:[self copyClientCertificate2]];
[request setCachePolicy:ASIDoNotReadFromCacheCachePolicy];
[request setDelegate:self];
[request setUseCookiePersistence:YES];
[request startAsynchronous];
[request setDidFinishSelector:#selector(ConnectFinished2:)];
However, I can see in my server that the second call is using the first certificate even though it is getting another certificate on copyClientCertificate2. So is the certificate getting cached? How can I explicitly tell the second ASIHTTPRequest to use the second certificate?
Note: it is 2 different URLS but the same domain.
Thanks!
If you can, try changing the DNS settings so you will have two different domains. That should solve your cache problems.
You have to use this method of Matt Thompson's ASIHTTP unmaintained Library [[ASIDownloadCache sharedCache] removeCachedDataForURL: yourURLReference];
I have a WCF web-service. If I just put the URL into the browser, I will get the error message: Forbidden. But if I post data through Fetcher(a HTTP Simulator in OS X), I can get the correct return value.
Now, I tried to use NSURLConnection to post data to the web-service and fetch the return value.
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:postURL];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLResponse * response = nil;
NSError * error = [[NSError alloc] init];
receivedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString * receivedStr = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
But all I get is just the html code of the error page I can see from the browser(that forbidden message).
Please help me figure it out. Thanks in advance.
EDIT:
I set up a PHP server and try to do the same thing. I works perfectly. Therefore, I highly doubt it is the WCF problem. Anyone has some good ideas?
if you use generated .svc service you need to :
change
[request setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
to
[request addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-type"];
also you need to SOAPAction field according to operation you request
What is you postData?
I'm trying to convert most of a project's NSURLRequests that use NSURLConnection to ASIHTTPRequest calls. I came across an issue about setting the HTTPBody in an ASIHTTPRequest. Here's what I had for the NSURLRequest call:
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]];
[req setHTTPMethod:#"POST"];
[req setHTTPBody:[self.paramString dataUsingEncoding:NSUTF8StringEncoding]];
[self _sendRequest:req];
And to convert to ASI, this is what I have so far:
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:self.urlString]];
[request setRequestMethod:#"POST"];
[request appendPostData:[self.paramString dataUsingEncoding:NSUTF8StringEncoding]];
[request setCompletionBlock:^{
NSLog(#"ASIHTTP request finished: %#", [request responseString]);
// Do stuff here
}];
[request setFailedBlock:^{
NSError *error = [request error];
NSLog(#"ASIHTTP error: %#", [error description]);
}];
[request startAsynchronous];
Although when I run this with ASI, I get this error:
ASIHTTP error: Error Domain=ASIHTTPRequestErrorDomain Code=6 "Unable to start HTTP connection" UserInfo=0x10ddf6b0 {NSLocalizedDescription=Unable to start HTTP connection}
EDIT This error was fixed, but data is still not being transmitted correctly due to the body not being set.
I'm thinking this has to do with me not setting the body correctly. I tried using ASI's setPostBody, but that only produced the same result. This works fine with NSURLRequest, but not ASI. I'm pretty sure it's really simple and I just haven't explored ASI's full library quite yet, but I was just wondering if anyone had any suggestions. I have read the documentation, but I couldn't find what I was looking for.
Thanks!
Could you check that
self.paramString
is correct? How does it look like?
I ended up using ASIFormDataRequest and setting values and keys. That seemed to work!