Re: NSURLConnection upload to iDisk works with iPhone OS 2.x but fails on 3.x
Jens, thank you for your answer. On Sep 27, 2009, at 7:59 PM, Jens Alfke wrote: On Sep 27, 2009, at 2:25 AM, Sergey Shapovalov wrote: This makes me think that chunked upload from stream via NSURLConnection has been broken in iPhone OS 3.x. Unfortunately, in real life I can't upload my file by using setHTTPBody instead of setHTTPBodyStream because it's too big to store in memory. That sounds plausible :( Is there a way you can capture the HTTP traffic to see exactly what's going on? Ordinarily I use the tcpflow utility for this, but it's not possible to install that on an iPhone. I think tcpdump can be used from a Mac/PC to capture packets from other devices on the LAN. Yes, I can try running the code in iPhone Simulator and capturing the traffic, or run it on iPhone and use the Mac as wi-fi proxy... Well, I'll try and compare the traffic generated with 2.2.1 and 3.0 executables. In any case, you should repost your questions on the macnetworkprog mailing list — this looks like a CFNetwork problem, and some of the engineers who work on that read that list. Thanks for the advice! Will try doing so. Unfortunately, in real life I can't upload my file by using setHTTPBody instead of setHTTPBodyStream because it's too big to store in memory. Have you tried memory-mapping? Use [NSData dataWithContentsOfMappedFile:]. No, I haven't... Well, that is definitely another option worth of trying. Thank you, this idea didn't come to my mind before! Best regards, Sergey.___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSURLConnection upload to iDisk works with iPhone OS 2.x but fails on 3.x
On Sep 27, 2009, at 2:25 AM, Sergey Shapovalov wrote: This makes me think that chunked upload from stream via NSURLConnection has been broken in iPhone OS 3.x. Unfortunately, in real life I can't upload my file by using setHTTPBody instead of setHTTPBodyStream because it's too big to store in memory. That sounds plausible :( Is there a way you can capture the HTTP traffic to see exactly what's going on? Ordinarily I use the tcpflow utility for this, but it's not possible to install that on an iPhone. I think tcpdump can be used from a Mac/PC to capture packets from other devices on the LAN. In any case, you should repost your questions on the macnetworkprog mailing list — this looks like a CFNetwork problem, and some of the engineers who work on that read that list. Unfortunately, in real life I can't upload my file by using setHTTPBody instead of setHTTPBodyStream because it's too big to store in memory. Have you tried memory-mapping? Use [NSData dataWithContentsOfMappedFile:]. —Jens___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSURLConnection upload to iDisk works with iPhone OS 2.x but fails on 3.x
Hello again. It looks like I've got more info on the issue. I've performed some additional investigation and figured out that if you substitute the lines NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath: filePath]; [request setHTTPBodyStream: stream]; with NSData* outgoingData = [str dataUsingEncoding: NSUTF8StringEncoding]; [request setHTTPBody: outgoingData]; then the code works perfectly with both 2.2.1 and 3.0. However, the original code works on 2.2.1 but fails on 3.0 and 3.1. This makes me think that chunked upload from stream via NSURLConnection has been broken in iPhone OS 3.x. Unfortunately, in real life I can't upload my file by using setHTTPBody instead of setHTTPBodyStream because it's too big to store in memory. So, if anybody sees a mistake in what I'm doing, please tell me. Otherwise, I'll post a bug to radar... However, that won't help me much because this issue a stopper for the new version of my app which I'm preparing for the App Store now. Best regards, Sergey. On Sep 27, 2009, at 12:28 AM, Sergey Shapovalov wrote: Hello. I'm using a very simple code snippet to upload a small file to my MobileMe iDisk. The problem is that it perfectly works with iPhone OS 2.2.1, but fails on 3.0. Now I'm trying to figure out whether that's a bug in iPhone OS 3.0, or I am doing something wrong and 2.2.1 is just more tolerant to my mistakes than 3.0. Here is my code. static NSString* kMobileMeUserName = ...; static NSString* kMobileMePassword = ...; - (void)upload { NSString* tmpFolderPath = [NSHomeDirectory() stringByAppendingPathComponent: @"tmp"]; NSString* filePath = [tmpFolderPath stringByAppendingPathComponent: @"test.txt"]; NSString* str = @"1234567890"; [str writeToFile: filePath atomically: NO encoding: NSUTF8StringEncoding error: NULL]; NSURL* url = [NSURL URLWithString: [NSString stringWithFormat: @"https://idisk.me.com/ %@/Documents/test.txt", kMobileMeUserName]]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL: url]; [request setHTTPMethod: @"PUT"]; NSDictionary* fileAttr = [[NSFileManager defaultManager] fileAttributesAtPath: filePath traverseLink: YES]; unsigned long long uploadSize = [fileAttr fileSize]; if ( uploadSize > 0 ) { NSNumber* num = [NSNumber numberWithUnsignedLongLong: uploadSize]; [request setValue: [num stringValue] forHTTPHeaderField: @"Content- Length"]; NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath: filePath]; [request setHTTPBodyStream: stream]; [NSURLConnection connectionWithRequest: request delegate: self]; } } In my controller (which is registered as NSURLConnection delegate) I implement all of NSURLConnection delegate methods and just call NSLog from them so that I can see in the log how the operation performs. I return YES for canAuthenticateAgainstProtectionSpace and from connectionShouldUseCredentialStorage. When I receive authentication challenge, I act like this: - (void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge*)challenge { NSLog(@"didReceiveAuthenticationChallenge"); NSURLCredential* cred = [NSURLCredential credentialWithUser: kMobileMeUserName password: kMobileMePassword persistence: NSURLCredentialPersistenceNone]; [challenge.sender useCredential: cred forAuthenticationChallenge: challenge]; } Now, here is what I see in console when I run this code with 2.2.1: willSendRequest connectionShouldUseCredentialStorage didSendBodyData didReceiveAuthenticationChallenge didSendBodyData didReceiveResponse connectionDidFinishLoading Everything works all right, and I can find the test.txt file (10 bytes in size) on my iDisk in the Documents folder. And this is how the same code runs in 3.0: willSendRequest connectionShouldUseCredentialStorage canAuthenticateAgainstProtectionSpace didReceiveAuthenticationChallenge didSendBodyData canAuthenticateAgainstProtectionSpace didReceiveAuthenticationChallenge For some reason I receive authentication challenge for the second time, and after that no more delegate methods are called. And the test.txt file never appears on the iDisk. Moreover - I tried deriving MyURLConnection from NSURLConnection and overriding init... and dealloc in it; from there, I just call super methods and add NSLog. This way I could see that the URL connection deallocs after the second authentication challenge - without having called connectionDidFinishLoading: or connection:didFailWithError: on the d
NSURLConnection upload to iDisk works with iPhone OS 2.x but fails on 3.x
Hello. I'm using a very simple code snippet to upload a small file to my MobileMe iDisk. The problem is that it perfectly works with iPhone OS 2.2.1, but fails on 3.0. Now I'm trying to figure out whether that's a bug in iPhone OS 3.0, or I am doing something wrong and 2.2.1 is just more tolerant to my mistakes than 3.0. Here is my code. static NSString* kMobileMeUserName = ...; static NSString* kMobileMePassword = ...; - (void)upload { NSString* tmpFolderPath = [NSHomeDirectory() stringByAppendingPathComponent: @"tmp"]; NSString* filePath = [tmpFolderPath stringByAppendingPathComponent: @"test.txt"]; NSString* str = @"1234567890"; [str writeToFile: filePath atomically: NO encoding: NSUTF8StringEncoding error: NULL]; NSURL* url = [NSURL URLWithString: [NSString stringWithFormat: @"https://idisk.me.com/ %@/Documents/test.txt", kMobileMeUserName]]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL: url]; [request setHTTPMethod: @"PUT"]; NSDictionary* fileAttr = [[NSFileManager defaultManager] fileAttributesAtPath: filePath traverseLink: YES]; unsigned long long uploadSize = [fileAttr fileSize]; if ( uploadSize > 0 ) { NSNumber* num = [NSNumber numberWithUnsignedLongLong: uploadSize]; [request setValue: [num stringValue] forHTTPHeaderField: @"Content- Length"]; NSInputStream* stream = [NSInputStream inputStreamWithFileAtPath: filePath]; [request setHTTPBodyStream: stream]; [NSURLConnection connectionWithRequest: request delegate: self]; } } In my controller (which is registered as NSURLConnection delegate) I implement all of NSURLConnection delegate methods and just call NSLog from them so that I can see in the log how the operation performs. I return YES for canAuthenticateAgainstProtectionSpace and from connectionShouldUseCredentialStorage. When I receive authentication challenge, I act like this: - (void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge*)challenge { NSLog(@"didReceiveAuthenticationChallenge"); NSURLCredential* cred = [NSURLCredential credentialWithUser: kMobileMeUserName password: kMobileMePassword persistence: NSURLCredentialPersistenceNone]; [challenge.sender useCredential: cred forAuthenticationChallenge: challenge]; } Now, here is what I see in console when I run this code with 2.2.1: willSendRequest connectionShouldUseCredentialStorage didSendBodyData didReceiveAuthenticationChallenge didSendBodyData didReceiveResponse connectionDidFinishLoading Everything works all right, and I can find the test.txt file (10 bytes in size) on my iDisk in the Documents folder. And this is how the same code runs in 3.0: willSendRequest connectionShouldUseCredentialStorage canAuthenticateAgainstProtectionSpace didReceiveAuthenticationChallenge didSendBodyData canAuthenticateAgainstProtectionSpace didReceiveAuthenticationChallenge For some reason I receive authentication challenge for the second time, and after that no more delegate methods are called. And the test.txt file never appears on the iDisk. Moreover - I tried deriving MyURLConnection from NSURLConnection and overriding init... and dealloc in it; from there, I just call super methods and add NSLog. This way I could see that the URL connection deallocs after the second authentication challenge - without having called connectionDidFinishLoading: or connection:didFailWithError: on the delegate. So, has anybody faced the same problem? Does anybody have an idea concerning what may be going wrong? Should I post a bug report to radar? Can anyone suggest a workaround? Any ideas are very welcome! I can send a simple sample project illustrating the problem on demand to anyone interested. Best regards, Sergey. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com