0

I want to send iPhone image to server database. I wrote following code. I am getting data mismatch exception and not able to resolve it. Could anyone please help me out.

Code on iPhone side:

- (void) uploadUserInfo:(NSString*)userId profilePic:(UIImage*)profilePic {

    __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: [NSURL URLWithString:[NSString stringWithFormat:@"%@/%d/uploadUserInfo?cultureDetect=false", dataUrl, currentAppID]]];

    [request setPostValue:userId forKey: @"userId"];
    // Upload an image
    [request addPostValue:@"pic.jpg" forKey:@"fileName"];
    NSData* imageData = UIImageJPEGRepresentation(profilePic, 1);
    [request setData:imageData withFileName:@"pic.jpg" andContentType:@"image/jpeg" forKey:@"profilePic"];

    [request setDelegate:self];
    [request setDidFinishSelector:@selector(uploadRequestFinished:)];
    [request setDidFailSelector:@selector(uploadRequestFailed:)];

    [queue addOperation: request];
    [queue go];

}

Code on ASP.NET MVC website Controller:

    public void uploadUserInfo(string userId, string fileName, byte[] profilePic)
    {
        int ID;
        if (int.TryParse(appId, out ID) && fileName != null && profilePic != null)
        {
            Image model = new Image();
            System.Drawing.Image image = System.Drawing.Image.FromStream(new System.IO.MemoryStream(profilePic));
            System.Drawing.Point maxSize = FileUtils.GetImageMaxSize(Image.ImageTypeEnum.TableCellImage);
            System.Drawing.Image thumb = ImageUtilities.GetFixedSizeImage(image, InterpolationMode.HighQualityBicubic, null, PixelFormat.Format32bppArgb, maxSize.X, maxSize.Y, false);
            byte[] resizedContent = ImageUtilities.GetBytesFromImage(thumb, ImageFormat.Png);
            model.AmendedDateTime = DateTime.Now;
            model.ApplicationId = ID;
            model.ImageType = Image.ImageTypeEnum.TableCellImage;
            string contentType = ImageUtilities.GetContentType(resizedContent);

            FileInfo f = new FileInfo(fileName);
            string name = f.Name.Substring(0, f.Name.Length - f.Extension.Length);
            string extension = f.Extension.Substring(1);

            BinaryFile file = new BinaryFile()
            {
                ContentType = contentType,
                FileName = name,
                FileExtension = extension
            };

            file.Data = resizedContent;
            model.BinaryFile = file;

            this.DataContext.Images.Table.InsertOnSubmit(model);

            ValidateAndSubmitChanges();
        }
        return;
    }

I have been getting following error before my method start executing. i.e. I guess MVC engine throwing exception directly when data type mismatched.

 [FormatException]: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters. 
   at System.Convert.FromBase64String(String s)
   at System.Web.Mvc.ByteArrayModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__4()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

I tried converting NSData to Byte but ASIHTTPRequest doesn't allow to setData as Byte data type:

    NSUInteger len = [imageData length];
    Byte *byteData = (Byte*)malloc(len);
    memcpy(byteData, [imageData bytes], len);
    [request setData:byteData withFileName:@"pic.jpg" andContentType:@"image/jpeg" forKey:@"profilePic"];

Conversion to Base64 gives the same exception!

using ASIHTTPRequest inbuilt static method:

  NSData* imageData = UIImageJPEGRepresentation(profilePic, 1);
  [request setData:[ASIHTTPRequest base64forData:imageData] withFileName:@"pic.jpg" andContentType:@"image/jpeg" forKey:@"profilePic"];

using method given at this thread:

    NSData* imageData = UIImageJPEGRepresentation(profilePic, 1);
    [request setData:[NSString base64StringFromData:imageData length:[imageData length]]  withFileName:@"pic.jpg" andContentType:@"image/jpeg" forKey:@"profilePic"];
Community
  • 1
  • 1
Paresh Masani
  • 7,474
  • 12
  • 73
  • 139

2 Answers2

2

This has annoyed me a lot! I just needed to replace Byte[] with HttpPostedFileBase which automatically handles posted files.

iPhone code:

    - (void) uploadUserInfo:(NSString*)userId profilePic:(UIImage*)profilePic {

    __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: [NSURL URLWithString:[NSString stringWithFormat:@"%@/app/%d/phone/uploadUserInfo?cultureDetect=false", dataUrl, currentAppID]]];

    NSData* imageData = UIImageJPEGRepresentation(profilePic, 1);
    [request setData:imageData  withFileName:@"pic.jpg" andContentType:@"image/jpeg" forKey:@"imageFile"];

    [request setDelegate:self];
    [request setDidFinishSelector:@selector(uploadRequestFinished:)];
    [request setDidFailSelector:@selector(uploadRequestFailed:)];

    [queue addOperation: request];
    [queue go];
}

ASP.NET MVC Controller code:

public void uploadUserInfo(HttpPostedFileBase imageFile)
{
       // Process imageFile
}
Paresh Masani
  • 7,474
  • 12
  • 73
  • 139
0

From the error you listed:

[FormatException]: The input is not a valid Base-64 string as it contains a non-base 64 character...

I'm guessing that you need to Base64 encode the data going up to your server.

So I'd recommend using a Base64 library to encode your data.

And to find out how to do that, here's another question that has the implementation details. The NSData category I use in my own code is in the answer authored by Alex Reynolds.

Community
  • 1
  • 1
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • Hi Michael, thanks for the info. I have already went through the link you sent me. I tried using [ASIHTTPRequest base64forData:imageData] static method as edited in my original question but it gives same exception! Also if I remove sending imagedata then everything else works perfectly fine! So there must be something to do with NSData on objective-c and byte on ASP.NET MVC! Not sure what's going on. – Paresh Masani Dec 01 '11 at 15:14
  • I just tried using those categories authored by Alex Reynolds but same exception! Edited the question. – Paresh Masani Dec 01 '11 at 15:41