任何熟悉使用“Twitpic api”将图片上传到Twitter的源代码的人都可以告诉我为什么在上传图片时会收到0响应代码?
这是我的代码:
- (BOOL)uploadImageToTwitpic:(UIImage*)image
withMessage:(NSString*)theMessage
username:(NSString*)username
password:(NSString*)password
{
NSString *stringBoundary, *contentType, *message, *baseURLString, *urlString;
NSData *imageData;
NSURL *url;
NSMutableURLRequest *urlRequest;
NSMutableData *postBody;
// Create POST request from message, imageData, username and password
baseURLString = kTwitpicUploadURL;
urlString = [NSString stringWithFormat:@"%@", baseURLString];
url = [NSURL URLWithString:urlString];
urlRequest = [[[NSMutableURLRequest alloc] initWithURL:url] autorelease];
[urlRequest setHTTPMethod:@"POST"];
// Set the params
message = ([theMessage length] > 1) ? theMessage : @"Here's my new Light Table collage.";
imageData = UIImageJPEGRepresentation(image, kTwitpicImageJPEGCompression);
// Setup POST body
stringBoundary = [NSString stringWithString:@"0xKhTmLbOuNdArY"];
contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", stringBoundary];
[urlRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];
// Setting up the POST request's multipart/form-data body
postBody = [NSMutableData data];
[postBody appendData:[[NSString stringWithFormat:@"\r\n\r\n--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"source\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"lighttable"] dataUsingEncoding:NSUTF8StringEncoding]]; // So Light Table show up as source in Twitter post
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"username\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:username] dataUsingEncoding:NSUTF8StringEncoding]]; // username
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"password\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:password] dataUsingEncoding:NSUTF8StringEncoding]]; // password
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"message\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:message] dataUsingEncoding:NSUTF8StringEncoding]]; // message
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"media\"; filename=\"%@\"\r\n", @"lighttable_twitpic_image.jpg" ] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Type: image/jpg\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; // jpeg as data
[postBody appendData:[[NSString stringWithString:@"Content-Transfer-Encoding: binary\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:imageData]; // Tack on the imageData to the end
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[urlRequest setHTTPBody:postBody];
NSLog(@"data=======>%@",postBody);
NSLog(@"URLReq========>%@",urlRequest);
// Spawn a new thread so the UI isn't blocked while we're uploading the image
[NSThread detachNewThreadSelector:@selector(uploadingDataWithURLRequest:) toTarget:self withObject:urlRequest];
return YES; // TODO: Should raise exception on error
}
- (void)uploadingDataWithURLRequest:(NSURLRequest*)urlRequest {
// Called on a separate thread; upload and handle server response
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[urlRequest retain]; // Retain since we autoreleased it before
// Send the request
NSHTTPURLResponse *urlResponse;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&urlResponse
error:&error];
NSString *responseString = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding];
// Handle the error or success
// If error, create error message and throw up UIAlertView
NSLog(@"Response Code: %d", [urlResponse statusCode]);
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
NSLog(@"urlResultString: %@", responseString);
NSString *match = [responseString stringByMatching:@"http[a-zA-Z0-9.:/]*"]; // Match the URL for the twitpic.com post
NSLog(@"match: %@", match);
// Send back notice to delegate
[delegate twitpicEngine:self didUploadImageWithResponse:match];
}
else {
NSLog(@"Error while uploading, got 400 error back or no response at all: %@", [urlResponse statusCode]);
[delegate twitpicEngine:self didUploadImageWithResponse:nil]; // Nil should mean "upload failed" to the delegate
}
[pool drain];
[responseString release];
[urlRequest release];
}
答案 0 :(得分:1)
修改:我建议您阅读this SO question,看看创建POST请求的其他方式是否有帮助。
我自己并不熟悉Twitpic API,但我会尝试提出一些可以帮助您缩小问题范围的建议。
我要检查的第一件事是POST正文的正确性。你创建它的代码是不必要的复杂和难以阅读,所以如果它可能存在错误我不会感到惊讶。我发布了一个修订版本(免责声明,我没有编译它),简化了创建并提高了性能。 (您正在创建一个自动释放的NSString和NSData对象的TON,并且每次只是为了追加数据字节而将字符串转换为数据。构建可变字符串并转换一次是一种更快更简单的方法。)
与此相关的是,当在方法的顶部声明每个变量时,读取代码有点困难。这在最近的C(或派生语言)标准中是不必要的,并且在首次使用变量时声明变量被认为是更好的做法。它不仅使代码更容易阅读,而且通常会修剪几条不必要的行。
以下是包含一些建议修订的代码。它们可以更容易地找出问题所在。
- (BOOL)uploadImageToTwitpic:(UIImage*)image
withMessage:(NSString*)theMessage
username:(NSString*)username
password:(NSString*)password
{
// Create POST request from message, imageData, username and password
NSString *baseURLString = kTwitpicUploadURL;
NSString *urlString = [NSString stringWithFormat:@"%@", baseURLString];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *urlRequest = [[[NSMutableURLRequest alloc] initWithURL:url] autorelease];
[urlRequest setHTTPMethod:@"POST"];
// Set the params
NSString *message = ([theMessage length] > 1) ? theMessage : @"Here's my new Light Table collage.";
// Setup POST body
NSString *stringBoundary = [NSString stringWithString:@"0xKhTmLbOuNdArY"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", stringBoundary];
[urlRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];
NSString *stringBoundarySeparator = [NSString stringWithFormat:@"\r\n--%@\r\n", stringBoundary];
NSMutableString *postString = [NSMutableString string];
[postString appendString:@"\r\n"];
[postString appendString:stringBoundarySeparator];
[postString appendString:@"Content-Disposition: form-data; name=\"source\"\r\n\r\n"];
[postString appendString:@"lighttable"]; // So Light Table shows up as source in Twitter
[postString appendString:stringBoundarySeparator];
[postString appendStringWithFormat:@"Content-Disposition: form-data; name=\"username\"\r\n\r\n%@", username];
[postString appendString:stringBoundarySeparator];
[postString appendStringWithFormat:@"Content-Disposition: form-data; name=\"password\"\r\n\r\n%@", password];
[postString appendString:stringBoundarySeparator];
[postString appendStringWithFormat:@"Content-Disposition: form-data; name=\"message\"\r\n\r\n%@", message];
[postString appendString:stringBoundarySeparator];
[postString appendStringWithFormat:@"Content-Disposition: form-data; name=\"media\"; filename=\"%@\"\r\n", @"lighttable_twitpic_image.jpg"];
[postString appendString:@"Content-Type: image/jpg\r\n"]; // data as JPEG
[postString appendString:@"Content-Transfer-Encoding: binary\r\n\r\n"];
// Setting up the POST request's multipart/form-data body
NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[postString dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:UIImageJPEGRepresentation(image, kTwitpicImageJPEGCompression)]; // Tack on the image data to the end
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[urlRequest setHTTPBody:postBody];
NSLog(@"data=======>%@",postBody);
NSLog(@"URLReq========>%@",urlRequest);
// Spawn a new thread so the UI isn't blocked while we're uploading the image
[NSThread detachNewThreadSelector:@selector(uploadingDataWithURLRequest:) toTarget:self withObject:urlRequest];
return YES; // TODO: Should raise exception on error
}
// Called on a separate thread; upload and handle server response
- (void)uploadingDataWithURLRequest:(NSURLRequest *)urlRequest {
[urlRequest retain]; // Retain since we're using it in this method
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Send the request
NSHTTPURLResponse *urlResponse;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&urlResponse
error:&error];
NSString *responseString = [[[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding] autorelease];
// Handle the error or success
// If error, create error message and throw up UIAlertView
NSLog(@"Response Code: %d", [urlResponse statusCode]);
NSLog(@"Response String: %@", responseString);
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
NSString *match = [responseString stringByMatching:@"http[a-zA-Z0-9.:/]*"]; // Match the URL for the twitpic.com post
NSLog(@"match: %@", match);
// Send back notice to delegate
[delegate twitpicEngine:self didUploadImageWithResponse:match];
}
else {
NSLog(@"Error while uploading, got 400 error back or no response at all: %@", [urlResponse statusCode]);
[delegate twitpicEngine:self didUploadImageWithResponse:nil]; // Nil should mean "upload failed" to the delegate
}
[pool drain];
[urlRequest release];
}
有一件事可以帮助我们回答您的问题:您声明响应代码为0,但没有说出响应的其余部分(您在responseString
中记录的)是什么。由于您只打印,如果状态代码在[200,300]范围内,您可能无法看到问题的原因,即使Twitpic 可能将其传回给您。值得一试......(我在上面的代码中完成了这个。)