#iphone #ios #post #nsdata #nsurlrequest
#iPhone #iOS #Публикация #nsdata #nsurlrequest
Вопрос:
Я просмотрел множество сообщений о загрузке изображений через POST в iOS. Несмотря на обилие информации по этой теме, мне не удается корректно загрузить данные в формате JPEG, взятые из моей фотобиблиотеки iPhone Simulator. Данные, попавшие на сервер, представляют собой просто огромную строку в шестнадцатеричном формате. Разве NSData не должна быть просто потоком байтов? Я не понимаю, что происходит со всеми шестнадцатеричными значениями или почему этот код, похоже, работает для всех остальных.
Вот код, о котором идет речь:
-(void)uploadWithUserLocationString:(NSString*)userLocation{
NSString *urlString = @"http://some.url.com/post";
// set up the form keys and values (revise using 1 NSDictionary at some point - neater than 2 arrays)
NSArray *keys = [[NSArray alloc] initWithObjects:@"auth",@"text",@"location",nil];
NSArray *vals = [[NSArray alloc] initWithObjects:self.authToken,self.textBox.text,userLocation,nil];
// set up the request object
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
//Add content-type to Header. Need to use a string boundary for data uploading.
NSString *boundary = [NSString stringWithString:@"0xKhTmLbOuNdArY"];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
//create the post body
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:@"--%@rn",boundary] dataUsingEncoding:NSASCIIStringEncoding]];
//add (key,value) pairs (no idea why all the r's and n's are necessary ... but everyone seems to have them)
for (int i=0; i<[keys count]; i ) {
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"rnrn",[keys objectAtIndex:i]] dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@",[vals objectAtIndex:i]] dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[[NSString stringWithFormat:@"rn--%@rn",boundary] dataUsingEncoding:NSASCIIStringEncoding]];
}
[body appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name="image"rn"] dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Type: application/octet-streamrnrn"] dataUsingEncoding:NSASCIIStringEncoding]];
[body appendData:[NSData dataWithData:self.imageData]];
[body appendData:[[NSString stringWithFormat:@"rn--%@--rn",boundary] dataUsingEncoding:NSASCIIStringEncoding]];
// set the body of the post to the reqeust
[request setHTTPBody:body];
// make the connection to the web
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(returnString);
[keys release];
[vals release];
}
Спасибо за ваше время.
Ответ №1:
Этот код работает в моем приложении. Если вы не используете ARC, вам нужно будет изменить код, чтобы освободить что-либо выделенное.
// create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];
// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// post body
NSMutableData *body = [NSMutableData data];
// add params (all params are strings)
for (NSString *param in _params) {
[body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"rnrn", param] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@rn", [_params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
// add image data
NSData *imageData = UIImageJPEGRepresentation(imageToPost, 1.0);
if (imageData) {
[body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"; filename="image.jpg"rn", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:@"Content-Type: image/jpegrnrn"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[[NSString stringWithFormat:@"rn"] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"--%@--rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];
// set URL
[request setURL:requestURL];
Комментарии:
1. У вас когда-нибудь возникали проблемы с выполнением этой работы? Это почти точно мой код, и я даже изменил свой тип контента на «image / jpeg», как у вас. Возможно, моя проблема на стороне сервера, хотя я уверен, что это не так.
2. Никаких проблем, этот код работает в моем приложении для загрузки файлов JPG, снятых с камеры iPhone, на наш веб-сервер.
3. Не могли бы вы объяснить назначение имени файла =»image.jpg «? У меня этого нет в моем коде, я предположил, что это дополнительная информация, но, возможно, это необходимо?
4. Я хотел добавить комментарий здесь об этом коде. Возврат каретки и перевод строки, а также дополнительные тире имеют РЕШАЮЩЕЕ значение для того, как работает этот процесс. У вас должен быть двойной CR / LF в нужном месте и дополнительные тире в нужном месте. Я думал, что это просто так много лишнего, но это важно. Код XJone помог мне разобраться с моей проблемой, когда мне не хватало паршивого CR / LF, и моя загрузка не удалась. 1 для вас, сэр, и для этого вопроса.
5. Я не уверен. Я не писал код на стороне сервера, я отправляю в проприетарный API. Однако именование на сервере не влияет на код клиента.
Ответ №2:
я надеюсь, что этот код поможет кому-то еще…
//create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
//Set Params
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:60];
[request setHTTPMethod:@"POST"];
//Create boundary, it can be anything
NSString *boundary = @"------VohpleBoundary4QuqLuM1cE5lMwCy";
// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// post body
NSMutableData *body = [NSMutableData data];
//Populate a dictionary with all the regular values you would like to send.
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setValue:param1 forKey:@"param1-name"];
[parameters setValue:param2 forKey:@"param2-name"];
[parameters setValue:param3 forKey:@"param3-name"];
// add params (all params are strings)
for (NSString *param in parameters) {
[body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"rnrn", param] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@rn", [parameters objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
NSString *FileParamConstant = @"imageParamName";
NSData *imageData = UIImageJPEGRepresentation(imageObject, 1);
//Assuming data is not nil we add this to the multipart form
if (imageData)
{
[body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="%@"; filename="image.jpg"rn", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type:image/jpegrnrn" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[[NSString stringWithFormat:@"rn"] dataUsingEncoding:NSUTF8StringEncoding]];
}
//Close off the request with the boundary
[body appendData:[[NSString stringWithFormat:@"--%@--rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the request
[request setHTTPBody:body];
// set URL
[request setURL:[NSURL URLWithString:baseUrl]];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
if ([httpResponse statusCode] == 200) {
NSLog(@"success");
}
}];
Комментарии:
1. если у меня есть путь к изображению dev-demo.info.bh-in-15.webhostbox.net/dv/xyz/ulpoad/post / … тогда куда я должен поместить это в приведенный выше код
2. @Abhi NSData *ImageData = UIImageJPEGRepresentation(ImageObject, 1) замените эту строку .. загрузите изображение из path и преобразуйте в nsdata
3. это сбивает с толку, можете ли вы обновить его в своем ответе или в комментарии
4. @Abhi NSData *ImageData = [NSData dataWithContentOfFile:filePath]; укажите путь к файлу ur
Ответ №3:
Взгляните на пример проекта Apple SimpleURLConnections. Вы можете использовать PostController оттуда с несколькими изменениями.
Однако — это не совсем просто. Отличие от решения выше заключается в том, что Apple использует stream для передачи файла на сервер. Это гораздо удобнее для памяти, чем хранить закодированные данные изображения на протяжении всей загрузки. Это также намного сложнее.
Ответ №4:
NSData *imgData = UIImagePNGRepresentation(imgUser.image);
NSString *str=[NSString stringWithFormat:@"%@upload_image",appDelegate.strRoot];
NSString *urlString = [NSString stringWithFormat:@"%@",str];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];
NSMutableData *body = [NSMutableData data];
NSString *boundary = @"---------------------------14737809831466499882746641449";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
[body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name="file"; filename="a.jpg"rn" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-streamrnrn" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithData:imgData]];
[body appendData:[@"rn" dataUsingEncoding:NSUTF8StringEncoding]];
// parameter UserId
[body appendData:[[NSString stringWithFormat:@"--%@rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name="userid"rnrn"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[appDelegate.strUserID dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"rn" dataUsingEncoding:NSUTF8StringEncoding]];
// close form
[body appendData:[[NSString stringWithFormat:@"--%@--rn", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the request
[request setHTTPBody:body];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"%@",dict);
Комментарии:
1. большое вам спасибо за ваш код! другие фрагменты не работали, и разница с вашим заключалась в том, что вы закрываете форму границей.
Ответ №5:
Я вижу, что вы отправляете несколько файлов в одном запросе, верно?
Исходя из спецификации HTTP, вы должны использовать multipart / mixed Content-type внутри встраивания multipart / form-data
Пример по ссылке выше:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"
Content-type: multipart/mixed, boundary=BbC04y
--BbC04y
Content-disposition: attachment; filename="file1.txt"
Комментарии:
1. вы знаете, как получить все данные в php из этого