ios JSON解析错误Error Domain = NSCocoaErrorDomain Code=3840 上传文件并期待响应
Posted
技术标签:
【中文标题】ios JSON解析错误Error Domain = NSCocoaErrorDomain Code=3840 上传文件并期待响应【英文标题】:ios JSON parsing error Error Domain = NSCocoaErrorDomain Code=3840 when uploading file and expecting response 【发布时间】:2014-11-29 21:24:36 【问题描述】:更新见文末
我正在构建我的第一个 ios 应用程序,并且我创建了许多功能,应用程序连接到服务器并获取数据。在应用程序仅发送数据的函数中,如果一切正常,我将服务器设置为使用以下 JSON 响应进行回复:
$reply = array('thisReply'=>'SUCCESS');
echo CJSON::encode($reply);
我在我的应用程序的其他功能中尝试了这个,这些功能将数据发送到服务器,它就像一个魅力。这是我用来发出请求的代码:
(stringUrl 只是我的服务器字符串)
NSURL *url = [[NSURL alloc] initWithString:stringUrl];
NSString *postMessage = [[NSString alloc] initWithFormat:@"username=%@&password=%@&requestedDataEntry=%@", currentUser.username, password, requestedData];
//turn post string into data object
NSData *postData = [requestPostMessage dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
//post data legnth
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
//url request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
//set up request properties
[request setURL:requestURL];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:postData];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
//error attribute
NSError *error = [[NSError alloc] init];
//create response
NSURLResponse *response;
//json data
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//pass symptom history objects into an array
NSDictionary *jsonReponseData = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
我得到了正确的回复(键/值对 'thisReply'=>'SUCCESS')
这是我上传文件(并发送我的帖子数据)的功能,我从 *** 上的回复中复制了该文件:
NSURL *url = [[NSURL alloc] initWithString:stringUrl];
//get curent user username and password
User *currentUser = [[User alloc]initWithSavedUser];
NSString *password = passWordString; //(not actual code)
//get also send as sms string
NSString *sendSMS = [[NSString alloc] init];
if(smsBoolean)
sendSMS = @"YES";
else
sendSMS = @"NO";
//get file attached string
NSString *recordedMessageExists = [[NSString alloc] init];
if(recordedMessageBoolean)
recordedMessageExists = @"YES";
else
recordedMessageExists = @"NO";
NSDictionary *params = @@"username" : currentUser.username,
@"password" : password,
@"patientID" : patientID,
@"sendSMS" : sendSMS,
@"message" : message,
@"attachFile" : recordedMessageExists;
//get an array with the files path
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//copy documents path into an nstring
NSString *documentsPath = [pathsArray objectAtIndex:0];
//get path for recorded message
NSString *soundFilePath = [documentsPath stringByAppendingPathComponent:fileNameString];
//create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
//set request http method and url
[request setHTTPMethod:@"POST"];
[request setURL:url];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
// Append parameters data into post url
NSMutableData *body = [NSMutableData data];
[params enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop)
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]];
];
// attach file if user has added one
if(recordedMessageBoolean)
//get filename
NSString *filename = [soundFilePath lastPathComponent];
NSData *data = [NSData dataWithContentsOfFile:soundFilePath];
NSString *mimetype = [self mimeTypeForPath:soundFilePath];
//append file to post body
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", @"messageFile", filename] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:data];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
//set request's body
[request setHTTPBody:body];
//post data legnth
NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
// create url response
NSURLResponse *response;
//set up NSerror
NSError *error = [[NSError alloc] init];
//-- Getting response form server
//send update to server
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//pass reply into an NSDictionary
NSDictionary *jsonReponseData = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
还有 mimeTypeForPath 函数
- (NSString *)mimeTypeForPath:(NSString *)path
// get a mime type for an extension using MobileCoreServices.framework
CFStringRef extension = (__bridge CFStringRef)[path pathExtension];
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);
NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));
CFRelease(UTI);
return mimetype;
帖子数据连同声音文件被正确发送到服务器,服务器执行其所有功能,但是当它返回 json 回复时,已设置 responseData,但 NSDictionary jsonResponseData 为 nil,我收到错误报告说:
JSON parsing error Error Domain = NSCocoaErrorDomain Code=3840
和
NSDebugDescription @"JSON text did not begin with an array or object....".
我在网上搜索了这些错误,所有结果都说当 JSON 字符串有问题时会出现此错误,但是相同的 json 字符串在第一个函数中起作用,所以我认为这一定是我做错了有请求,但我从各地得到了所有代码,很难说出导致错误的原因。有人可以帮帮我吗?
更新
我记录了响应数据,结果发现整个网页都是 JSON 响应,这就是导致问题的原因。
更新 2 和最终答案
我发现了错误。我有代码将发送的文件临时复制到服务器,然后将其附加到电子邮件中并将其发送出去(最后删除了文件)。但是我在 if 检查之外有这个检查要附加的文件是否是甚至由应用程序发布。在我进行 if 检查后,此错误在任何一种情况下都停止发生(有或没有附加文件)。
【问题讨论】:
顺便说一句,当你遇到直接的问题时,我建议你删除sendSynchronousRequest
的代码。你永远不想从主队列发出同步请求。
完成后我会在谷歌上搜索相关教程,谢谢
另请注意,在您的原始x-www-form-urlencoded
请求中,您没有对参数进行百分比编码。例如,如果密码中包含&
或+
,则此代码将不起作用。始终对您的 x-www-form-urlencoded
请求进行百分比编码(但不是您的 multipart/form-data
请求)。
【参考方案1】:
你应该检查responseData
的内容,例如,
NSLog(@"responseData = %@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
我怀疑您会发现它不符合有效的 JSON。编辑您的问题,向我们展示它所说的内容。
您可能想要记录 response
对象并确保 statusCode
也是 200。如果不是 200,那么你有一些服务器相关的问题。
顺便说一句,您的 JSON 解析例程不使用 error
参数。每当您的代码出现问题时,请确保您使用了所有可用的错误日志记录。
【讨论】:
是的,你是对的.....我将整个网页作为 JSON 响应:S。我不知道为什么 它通常是一个 html 页面,报告由以下任一原因引起的错误: (a) 服务器 php 代码中的错误; (b) 服务器在请求中查找未正确提供的内容,但服务器代码没有妥善处理错误;或 (c) 请求中的一些简单错误(例如返回 HTML 页面的错误 URL,通知您 404 服务器代码)。这就是为什么我建议查看response
对象中的statusCode
,因为这有时可以帮助您以编程方式诊断问题的根源。
我发现了错误。我有代码将发送的文件临时复制到服务器,然后将其附加到电子邮件中并将其发送出去(最后删除了文件)。但是我在 if 检查之外进行了此操作,以检查应用程序是否甚至发布了要附加的文件。在我进行 if 检查后,此错误在任何一种情况下都停止发生(有或没有附加文件)。非常感谢 Rob :)。以上是关于ios JSON解析错误Error Domain = NSCocoaErrorDomain Code=3840 上传文件并期待响应的主要内容,如果未能解决你的问题,请参考以下文章
Error Domain = NSCocoaErrorDomain Code=3840 "操作无法完成。(Cocoa 错误 3840。)