问题
hiii, i'm using wcf SOAP services for my app and i send the request like below.
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];
in the above request there is an element ActivityStreamImagesBytes which is base64binary parameter i have to pass the image.
I've tried using many different formats.
here is wcf service screenshot
and here is the server side code
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 "";
}
the server is expecting a byte array and i dont know how to send it?
And i dont know what a base64binary data type is?
Do I have to send the base64 encoded string or byte array or just data of image from NSData *data = UIImageJPEGRepresentation([UIImage imageNamed:@"popular.png"], 0.7);
Any help is appreciable
回答1:
The WCF service clearly asks for base64binary so you have to send it in base64binary only.
base64binary is nothing but base64 encoded binary data.
1) Convert the image to binary using the following code snippet
NSData *binaryImageData = UIImageJPEGRepresentation([UIImage imageNamed:@"Photo.png"], 0.0);
2) Encode the binary into base64 format
Here is the class that I use to handle base64 binary and 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
Here is the way to convert binary into base64binary
NSString *Base64Binary=[base64BinaryandImagehandler base64BinaryStringFromBinaryData:binaryImageData length:binaryImageData.length];
You can find more about here as well
Here is the base64 encoding and decoding part in 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);
}
Anyhow you can ignore about the C# part since you are doing iPhone part only.
You can use the below link to test if your encoded base 64 is proper.
base64toimage converter
Update 1 Here is the code that will confirm if the received string is in base64 format or not
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;
}
}
Reference
The below code will create a image under Images folder for the given arriving base64 data and filename of your choice for example duraiamuthan.jpg and return the path of the image so that you can update it in the DB (It will check if the arriving the data is in base64 or binary[just in case WCF framework converts the base64 to binary internally])
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 "";
}
}
Update 2 (for timeout issues)
NSURLRequest and NSMutableURLRequest default timeout period is 60 seconds depending upon the Internet connectivity,Internet Traffic congestiion at webserver,ImageCreating time and all it may not be enough.so you can set the value higher than that using the following syntax
[urlReqObj setTimeoutInterval:180];the timeout interval is in seconds only.Increase the ConnectionTimeout in IIS default value is 120 seconds sometimes if so many requests queue in the request will fail.Increasing the ConnectionTimeOut will help.(This timeout is also for idle time of a connection).To set it in IIS Advanced Settings Click on your
service in IIS Manager -> Advanced Settings -> Connection Limitsand there you can set the timeout or you could simple override the connection timeout inweb.config.Turn on
Keep-alive in IISso that same connection is reused thus increasing the effeceincy of IIS. Click on yourservice in IIS Manager -> Advanced Settings -> Connection Limits -> Enable HTTP Keep-AlivesIf you plan to store the binary of image in DB.you can increase the DB
connectiontimeoutinconnectionstringor you can increase thesqlcommandtimeout
Hope this helps. Feel free to ask if you have any doubts
回答2:
Hiii, I've got what my problem is
On server side, its expecting a byte array,
So, I've to send my request as follows.
Converting the base64 string into byte array
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];
I've hosted the services and there i've seen the xml format of the request. Any way thank you @Duraiamuthan.H
来源:https://stackoverflow.com/questions/29077775/upload-image-from-iphone-to-server-using-wcf-service-using-soap