Cargar image desde iPhone al server usando el service WCF usando SOAP

Hola, estoy usando services SOF de wcf para mi aplicación y envío la request como a continuación.

postStr = [NSString stringWithFormat:@"<?xml version=\"1.0\"?>\n" "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" "<s:Body>\n" "<InsUpdDelActivityInfo xmlns=\"http://tempuri.org/\">\n" "<objEventsContent xmlns:d4p1=\"http://schemas.datacontract.org/2004/07/iCampuslite.Model.ActivityStream\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">\n" "<d4p1:ActCommentId i:nil=\"true\" />\n" "<d4p1:ActSubTypeCd i:nil=\"true\" />\n" "<d4p1:ActType>Status</d4p1:ActType>\n" "<d4p1:ActTypeCd>1</d4p1:ActTypeCd>\n" "<d4p1:ActivityAnswersList />\n" "<d4p1:ActivityComments />\n" "<d4p1:ActivityId i:nil=\"true\" />\n" "<d4p1:ActivityLike />\n" "<d4p1:ActivityName>%@</d4p1:ActivityName>\n" "<d4p1:ActivityStreamImagesBytes>%@</d4p1:ActivityStreamImagesBytes>\n" "<d4p1:AnswerDesc i:nil=\"true\" />\n" "<d4p1:AnswerId>0</d4p1:AnswerId>\n" "<d4p1:CommentDesc i:nil=\"true\" />\n" "<d4p1:CommentId i:nil=\"true\" />\n" "<d4p1:CreatedUserId>%@</d4p1:CreatedUserId>\n" "<d4p1:CreatedUserName i:nil=\"true\" />\n" "<d4p1:FileOrLinkName i:nil=\"true\" />\n" "<d4p1:IsLiked>0</d4p1:IsLiked>\n" "<d4p1:IsTotalSchool i:nil=\"true\" />\n" "<d4p1:LikeCount>0</d4p1:LikeCount>\n" "<d4p1:LinkImage i:nil=\"true\" />\n" "<d4p1:ObjTypeCdId i:nil=\"true\" />\n" "<d4p1:ObjTypeId i:nil=\"true\" />\n" "<d4p1:OperationMode>I</d4p1:OperationMode>\n" "<d4p1:OperationType i:nil=\"true\" />\n" "<d4p1:OperationTypeId i:nil=\"true\" />\n" "<d4p1:OrganizationId>%@</d4p1:OrganizationId>\n" "<d4p1:OtherActivityId i:nil=\"true\" />\n" "%@\n" "</objEventsContent>\n" "<ismobile>true</ismobile>\n" "</InsUpdDelActivityInfo>\n" "</s:Body>\n" "</s:Envelope>", statusText, [appDelegateObj.loginUserInfoDict valueForKey:@"a:UserId"], [appDelegateObj.loginUserInfoDict valueForKey:@"a:OrgId"], workspaceStr]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@iCampusliteMobileService/ActivityStreamSl.svc", appDelegateObj.baseURL]]]; NSString *messageLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postStr length]]; [request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"]; [request addValue:@"http://tempuri.org/IActivityStreamSl/InsUpdDelActivityInfo" forHTTPHeaderField:@"SOAPAction"]; [request addValue:messageLength forHTTPHeaderField:@"Content-Length"]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:[postStr dataUsingEncoding:NSUTF8StringEncoding]]; NSError *error = nil; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error]; 

en la request anterior hay un elemento ActivityStreamImagesBytes que es el parámetro base64binary que tengo que pasar la image.

He intentado usar muchos formattings diferentes.

Aquí hay una pantalla de service wcf aquí

y aquí está el código del lado del server

 public string byteArrayToImage(byte[] byteArrayIn,string fileName) { if (byteArrayIn != null) { ActivityStreamSl.LogMsg("Byte Array Count : "+byteArrayIn.Length.ToString(), "D:\\log.txt"); var serverfile = "D:somepath\somepath\somefolder"; var getfile = HelperClass.Filesavehelper(Constants.UploadPaths.ActivityStream, "testfilename.png", serverfile); FileStream file = new FileStream(getfile, FileMode.Create); file.Write(byteArrayIn, 0, byteArrayIn.Length); file.Close(); file.Dispose(); return getfile; } else { ActivityStreamSl.LogMsg("Byte array is null","D:\\log.txt"); } return ""; } 

el server está esperando una matriz de bytes y no sé cómo enviarlo? ¿Y no sé qué es un tipo de datos base64binary? ¿Debo enviar la cadena codificada base64 o la matriz de bytes o simplemente los datos de la image de NSData *data = UIImageJPEGRepresentation([UIImage imageNamed:@"popular.png"], 0.7);

Cualquier ayuda es apreciable

El service WCF solicita claramente base64binary, por lo que debe enviarlo solo en base64binary.

base64binary no es más que datos binarys codificados en base64 .

1) Convierta la image en binary usando el siguiente fragment de código

 NSData *binaryImageData = UIImageJPEGRepresentation([UIImage imageNamed:@"Photo.png"], 0.0); 

2) Codifique el binary en formatting base64

Aquí está la class que utilizo para manejar el binary base64 y el UIImage

  @interface base64BinaryandImagehandler:NSObject +(NSString *) base64BinaryStringFromBinaryData: (NSData *)data length: (int)length; +(UIImage*)Base64BinaryToImage:(NSString *)Base64; @end @implementation base64BinaryandImagehandler:NSObject static char base64EncodingTable[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; +(NSString *) base64BinaryStringFromBinaryData: (NSData *)data length: (int)length{ unsigned long ixtext, lentext; long ctremaining; unsigned char input[3], output[4]; short i, charsonline = 0, ctcopy; const unsigned char *raw; NSMutableString *result; lentext = [data length]; if (lentext < 1) return @""; result = [NSMutableString stringWithCapacity: lentext]; raw = [data bytes]; ixtext = 0; while (true) { ctremaining = lentext - ixtext; if (ctremaining <= 0) break; for (i = 0; i < 3; i++) { unsigned long ix = ixtext + i; if (ix < lentext) input[i] = raw[ix]; else input[i] = 0; } output[0] = (input[0] & 0xFC) >> 2; output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4); output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6); output[3] = input[2] & 0x3F; ctcopy = 4; switch (ctremaining) { case 1: ctcopy = 2; break; case 2: ctcopy = 3; break; } for (i = 0; i < ctcopy; i++) [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]]; for (i = ctcopy; i < 4; i++) [result appendString: @"="]; ixtext += 3; charsonline += 4; if ((length > 0) && (charsonline >= length)) charsonline = 0; } return result; } +(UIImage*)Base64BinaryToImage:(NSString *)Base64{ NSString* base64String=[[NSString alloc]initWithFormat:@"data:image/png;base64,%@",Base64]; NSURL *base64url = [NSURL URLWithString:base64String]; NSData *imageData = [NSData dataWithContentsOfURL:base64url]; UIImage *img=[UIImage imageWithData:imageData]; return img; } @end 

Esta es la forma de convertir el binary en base64binary

 NSString *Base64Binary=[base64BinaryandImagehandler base64BinaryStringFromBinaryData:binaryImageData length:binaryImageData.length]; 

También puedes encontrar más sobre aquí.

Aquí está la parte de encoding y deencoding de base64 en C #

 public static string Base64Encode(string plainText) { var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); return System.Convert.ToBase64String(plainTextBytes); } public static string Base64Decode(string base64EncodedData) { var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); } 

De todos modos, puede ignorar sobre la parte de C # ya que está haciendo solo parte de iPhone.

Puede usar el siguiente enlace para probar si su base codificada 64 es la correcta.

convertidor base64toimage

Actualización 1 Aquí está el código que confirmará si la cadena recibida está en formatting base64 o no

  private bool IsBase64String(string str){ try{ // If not exception is caught, then it is a base64 string MemoryStream stream = new MemoryStream(Convert.FromBase64String(str)); return true; } catch{ // If exception is caught, then I assumed it is a normal string return false; } } 

Referencia

El código siguiente creará una image debajo de la carpeta Imágenes para los datos de base64 que llegan y el nombre de file de su elección, por ejemplo, duraiamuthan.jpg y devolverá la ruta de la image para que pueda actualizarla en la database (Verificará si la llegada de la image los datos están en base64 o binary [por si el marco WCF convierte la base64 en binary internamente])

  public string Getpath_CreateImageFromEncodedData(string Base64EncodedData, string fileName) { string fileHandle = ""; try { if(IsBase64String(Base64EncodedData)) byte[] imageBytes = Convert.FromBase64String(Base64EncodedData); else byte[] imageBytes= Base64EncodedData; MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); ms.Write(imageBytes, 0, imageBytes.Length); fileHandle = System.Web.HttpContext.Current.Server.MapPath("Images/" + fileName); FileStream fsObj = new FileStream(fileHandle, FileMode.Create, FileAccess.Write); ms.WriteTo(fsObj); fsObj.Close(); ms.Close(); return fileHandle; } catch (Exception ex) { return ""; } } 

Actualización 2 (para problemas de time de espera)

  • NSURLRequest y NSMutableURL El período de espera pnetworkingeterminado es 60 segundos dependiendo de la conectividad a Internet, la congestión del tráfico de Internet en el server web, el time de creación de imágenes y todo puede no ser suficiente. Por lo tanto, puede establecer un valor superior al que usa la siguiente syntax [urlReqObj setTimeoutInterval:180]; el intervalo de time de espera solo está en segundos.

  • Aumentar el ConnectionTimeout en el valor pnetworkingeterminado de IIS es de 120 segundos a veces si faltan tantas requestes de queue en la request. El aumento de ConnectionTimeOut ayudará. (Este time de espera también es para el time de inactividad de una connection). Para configurarlo en IIS Advanced Settings Haga clic en su service in IIS Manager -> Advanced Settings -> Connection Limits y allí puede configurar el time de espera o puede simplemente anular el time de espera de connection en web.config .

  • Active Keep-alive in IIS para que la misma connection se reutilice y así aumente la eficacia de IIS. Haga clic en su service in IIS Manager -> Advanced Settings -> Connection Limits -> Enable HTTP Keep-Alives

  • Si planea almacenar el binary de la image en DB. Puede boost el time de connectiontimeout DB en connectionstring o puede boost sqlcommandtimeout

Espero que esto ayude. No dude en preguntar si tiene alguna duda

Hiii, tengo mi problema

En el lado del server, está esperando una matriz de bytes,

Por lo tanto, tengo que enviar mi request de la siguiente manera.

Convertir la cadena base64 en array de bytes

 postStr = [NSString stringWithFormat:@"<?xml version=\"1.0\"?>\n" "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" "<s:Body>\n" "<InsUpdDelActivityInfo xmlns=\"http://tempuri.org/\">\n" "<objEventsContent xmlns:d4p1=\"http://schemas.datacontract.org/2004/07/iCampuslite.Model.ActivityStream\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">\n" "<d4p1:ActCommentId i:nil=\"true\" />\n" "<d4p1:ActSubTypeCd i:nil=\"true\" />\n" "<d4p1:ActType>Status</d4p1:ActType>\n" "<d4p1:ActTypeCd>1</d4p1:ActTypeCd>\n" "<d4p1:ActivityAnswersList />\n" "<d4p1:ActivityComments />\n" "<d4p1:ActivityId i:nil=\"true\" />\n" "<d4p1:ActivityLike />\n" "<d4p1:ActivityName>%@</d4p1:ActivityName>\n" "<d4p1:ActivityStreamImagesBytes dt: dt:"Base64Binary"><dt:length>%d</dt:length><dt:byte>%@</dt:byte>......................................</d4p1:ActivityStreamImagesBytes>\n" "<d4p1:AnswerDesc i:nil=\"true\" />\n" "<d4p1:AnswerId>0</d4p1:AnswerId>\n" "<d4p1:CommentDesc i:nil=\"true\" />\n" "<d4p1:CommentId i:nil=\"true\" />\n" "<d4p1:CreatedUserId>%@</d4p1:CreatedUserId>\n" "<d4p1:CreatedUserName i:nil=\"true\" />\n" "<d4p1:FileOrLinkName i:nil=\"true\" />\n" "<d4p1:IsLiked>0</d4p1:IsLiked>\n" "<d4p1:IsTotalSchool i:nil=\"true\" />\n" "<d4p1:LikeCount>0</d4p1:LikeCount>\n" "<d4p1:LinkImage i:nil=\"true\" />\n" "<d4p1:ObjTypeCdId i:nil=\"true\" />\n" "<d4p1:ObjTypeId i:nil=\"true\" />\n" "<d4p1:OperationMode>I</d4p1:OperationMode>\n" "<d4p1:OperationType i:nil=\"true\" />\n" "<d4p1:OperationTypeId i:nil=\"true\" />\n" "<d4p1:OrganizationId>%@</d4p1:OrganizationId>\n" "<d4p1:OtherActivityId i:nil=\"true\" />\n" "%@\n" "</objEventsContent>\n" "<ismobile>true</ismobile>\n" "</InsUpdDelActivityInfo>\n" "</s:Body>\n" "</s:Envelope>", statusText, [byteArray length], byteArray[0], byteArray[1], .................................., [appDelegateObj.loginUserInfoDict valueForKey:@"a:UserId"], [appDelegateObj.loginUserInfoDict valueForKey:@"a:OrgId"], workspaceStr]; 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@blah....blah....blah....", appDelegateObj.baseURL]]]; NSString *messageLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postStr length]]; [request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"]; [request addValue:@"http://tempuri.org/blah......blah.....blah............" forHTTPHeaderField:@"SOAPAction"]; [request addValue:messageLength forHTTPHeaderField:@"Content-Length"]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:[postStr dataUsingEncoding:NSUTF8StringEncoding]]; NSError *error = nil; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];

He alojado los services y allí he visto el formatting xml de la request. De todos modos gracias @ Duraiamuthan.H