none
Apache Cordova error uploading cropped image to WCF web service from IOS RRS feed

  • Question

  • Hello guys,

    Please don't mark this as duplicate!

    On my IOS mobile application I am taking picture and then select this picture from gallery. After selecting this picture I am using ng-img-crop.js to crop this image and without saving this cropped image, trying to upload it to a server, the server side is C# WCF. (In this particular example I am trying to upload local IIS) But I am getting this error:

    ERROR: {"code":1,"source":"data:image/png;base64,iVBORw0KGgoAAAANSUhE...","target":"http://11.111.11.111/wcf/OCRService.svc/upload","http_status":null,"body":null,"exception":null}
    app.js (76,24)


    How can I upload this image to WCF service and get response back from this service?

    Here is my HTML:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
    
        <meta http-equiv="Content-Security-Policy" content="connect-src 'self' http://11.111.11.111/wcf/OCRService.svc/upload 'unsafe-eval' 'unsafe-inline'; default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
    
        <title>LoTTo</title>-->
    
        <!-- LoTTo references -->
        <link href="css/ionicons.css" rel="stylesheet" />
        <link href="css/ionic.css" rel="stylesheet" />
        <link href="css/ng-img-crop.css" rel="stylesheet" />
    
        <!-- Cordova reference, this is added to your app when it's built. -->
        <script src="scripts/angular.min.js"></script>
        <script src="scripts/ionic.bundle.js"></script>
        <script src="scripts/ng-cordova.min.js"></script>
        <script src="scripts/ng-img-crop.js"></script>
        <script src="cordova.js"></script>
        <script src="scripts/platformOverrides.js"></script>
        <script src="scripts/app.js"></script>
        <script src="scripts/index.js"></script>
        <script src="scripts/ng-file-upload-shim.min.js"></script>
        <script src="scripts/ng-file-upload.min.js"></script>
    
        <style>
            .cropArea {
                background: #E4E4E4;
                
                width: 300px;
                height: 300px;
            }
            .croppedArea {
                background: #E4E4E4;
                
                width: 300px;
    
            }
        </style>
    </head>
    <body ng-app="starter">
        <ion-header-bar class="bar bar-header bar-light">
            <h1 class="title">LoTTo</h1>
        </ion-header-bar>
        <ion-content ng-controller="ExampleController" padding="true">
            <button class="button button-full button-balanced icon-right ion-ios-camera" ng-click="takePhoto()">
                Resim Çek
            </button>
    
            <button class="button button-full button-balanced icon-right ion-images" ng-click="choosePhoto()">
                Resim Seç
            </button>
            <center>
                <div class="cropArea">
    
                    <img-crop image="myImage" result-image="myCroppedImage" chargement="'Loading'"
                              area-type="rectangle"
                              area-min-size="50"
                              result-image-format="image/jpeg"
                              result-image-quality="1"
                              result-image-size="{w:300, h:50}"></img-crop>
    
                </div>
                <div ng-show="myImage !== undefined">Gönderilecek Resim:</div>
                <div class="croppedArea"><img ng-src="{{myCroppedImage}}" ng-show="myImage !== undefined" id="image" /></div>
    
    
            </center>
            <button class="button button-full button-balanced icon-right ion-images" ng-click="upload(myCroppedImage);" ng-if="myImage !== undefined">
                Resim Yükle
            </button>
    
        </ion-content>    
    </body>
    </html>


    here is app.js:

    angular.module('starter', ['ionic', 'ngCordova', 'ngImgCrop', 'ngFileUpload'])
    
    .controller("ExampleController", ['$scope', '$cordovaCamera', 'Upload', '$timeout', '$cordovaFileTransfer', function ($scope, $cordovaCamera, Upload, $timeout, $cordovaFileTransfer) {
    
        $scope.takePhoto = function () {
            var options = {
                quality: 100,
                destinationType: Camera.DestinationType.DATA_URL,
                sourceType: Camera.PictureSourceType.CAMERA,
                allowEdit: true,
                encodingType: Camera.EncodingType.JPEG,
                targetWidth: 300,
                targetHeight: 300,
                popoverOptions: CameraPopoverOptions,
                saveToPhotoAlbum: true
            };
    
            $cordovaCamera.getPicture(options).then(function (imageData) {
                $scope.imgURI = "data:image/jpeg;base64," + imageData;
            }, function (err) {
                console.log(err);
                alert(err);
            });
        }
    
        $scope.choosePhoto = function () {
            var options = {
                quality: 100,
                destinationType: Camera.DestinationType.DATA_URL,
                sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
                allowEdit: true,
                encodingType: Camera.EncodingType.JPEG,
                targetWidth: 300,
                targetHeight: 300,
                popoverOptions: CameraPopoverOptions,
                saveToPhotoAlbum: false
            };
    
            $cordovaCamera.getPicture(options).then(function (imageData) {
                $scope.imgURI = "data:image/jpeg;base64," + imageData;
                $scope.myImage = $scope.imgURI;
    
            }, function (err) {
                console.log(err);
                alert(err);
            });
        }
    
        $scope.myCroppedImage = '';
    
        $scope.upload = function (dataUrl) {
    
        Upload.upload({
    
            url: 'http://192.168.1.20/wcf/upload',
            data: {
                file: Upload.dataUrltoBlob(dataUrl)
            },
    
        }).then(function (response) {
            $timeout(function () {
                $scope.result = response.data;
                console.log(response.data);
                alert(response.data);
            });
            console.log(response.data);
        }, function (response) {
            if (response.status > 0) $scope.errorMsg = response.status
                + ': ' + response.data;
            alert(response.status);
        });
    
    }
    
    }]);

    Here is my WCF Service Contract related part:

    [ServiceContract]
        public interface IOCRService
        {
    
            [OperationContract]
            [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/FileUpload?fileStream={fileStream}")]
            string OCRImage(Stream fileStream);

    Here is my WCF class related part:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class LoTToOCR : IOCRService

    Here is my WCF web config related part:

    <configuration>
        <system.serviceModel>
            <bindings>
                <!-- pick whichever binding you want .... -->
                <basicHttpBinding>
    
                    <binding name="OCRServiceSoap"
                        closeTimeout="00:10:00" openTimeout="00:10:00"
                        receiveTimeout="00:10:00" sendTimeout="00:10:00"
                        maxBufferSize="2147483647"
                        maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Mtom">
    
                        <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                            maxArrayLength="2147483647" maxBytesPerRead="2147483647"
                            maxNameTableCharCount="2147483647" />
                    </binding>
    
                </basicHttpBinding>
            </bindings>
            <services>
                <service behaviorConfiguration="basic" name="LoTToOCRService.LoTToOCR">
                    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="OCRServiceSoap"
                        contract="LoTToOCRService.IOCRService" />
                <host>
                        <baseAddresses>
                            <!--<add baseAddress=
                      "http://192.168.199.1/wcf/OCRService.svc"/>-->
                <add baseAddress=
                      "http://192.168.1.20/wcf/OCRService.svc"/>
                        </baseAddresses>
                    </host>
                </service>
            </services>

    Best Regards.

    Sunday, July 10, 2016 10:11 AM

Answers

  • Hi raysefo,

    >> [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/FileUpload?fileStream={fileStream}")]

    Based on above code, you have passed a Stream in UriTemplate, I made a test with this and I got error “type 'System.IO.Stream' is not convertible by 'QueryStringConverter'.  Variables for UriTemplate query values must have types that can be converted by 'QueryStringConverter'.” We could not pass Stream value in UriTemplate. I suggest you remove it, and test again with UriTemplate = "/FileUpload".

    Since I am not familiar with “ng-img-crop”, if your issue still exists after you remove fileStream, I would suggest you try below code to call OCRImage to check whether it is related with ng-img-crop.js and your service is correct.

    //service
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/FileUpload")]
            string OCRImage(Stream fileStream);       
        }
    
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Service1 : IService1
        {
            public string OCRImage(Stream fileStream)
            {
                string FilePath = @"D:\xx\test.png";
    
                int length = 0;
                using (FileStream writer = new FileStream(FilePath, FileMode.Create))
                {
                    int readCount;
                    var buffer = new byte[8192];
                    while ((readCount = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        writer.Write(buffer, 0, readCount);
                        length += readCount;
                    }
                }
                return "file upload is ok";
            }
    }
    
    //Html
    <head>
        <title></title>
             <meta charset="utf-8" />
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script type="text/javascript">
            function UploadFile() {
                // grab your file object from a file input
                fileData = document.getElementById("fileUpload").files[0];
                var data = new FormData();
                $.ajax({
                    url: 'http://localhost:35508/Service1.svc/FileUpload',
                    type: 'POST',
                    data: fileData,
                    cache: false,
                    dataType: 'json',
                    processData: false, // Don't process the files, Set to false as jQuery will tell the server its a query string request
                    contentType: "application/octet-stream",               
    success: function (data) {
                        alert('successful..');
                    },
                    error: function (data) {
                        alert('Some error Occurred!');
                    }
                });
    
            }
        </script>
    </head>
    <body>
        <div>
            <input type="file" id="fileUpload" value="" />
            <br />
            <br />
            <button id="btnUpload" onclick="UploadFile()">
                Upload
            </button>
        </div>
        <button id="btnDownload" onclick="DownloadFile()">
            Download
        </button>
    </body>
    

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Proposed as answer by Tony---- Tuesday, July 12, 2016 12:58 PM
    • Marked as answer by raysefo Tuesday, July 12, 2016 3:37 PM
    Monday, July 11, 2016 9:01 AM

All replies

  • Hi raysefo,

    >> [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/FileUpload?fileStream={fileStream}")]

    Based on above code, you have passed a Stream in UriTemplate, I made a test with this and I got error “type 'System.IO.Stream' is not convertible by 'QueryStringConverter'.  Variables for UriTemplate query values must have types that can be converted by 'QueryStringConverter'.” We could not pass Stream value in UriTemplate. I suggest you remove it, and test again with UriTemplate = "/FileUpload".

    Since I am not familiar with “ng-img-crop”, if your issue still exists after you remove fileStream, I would suggest you try below code to call OCRImage to check whether it is related with ng-img-crop.js and your service is correct.

    //service
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "/FileUpload")]
            string OCRImage(Stream fileStream);       
        }
    
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class Service1 : IService1
        {
            public string OCRImage(Stream fileStream)
            {
                string FilePath = @"D:\xx\test.png";
    
                int length = 0;
                using (FileStream writer = new FileStream(FilePath, FileMode.Create))
                {
                    int readCount;
                    var buffer = new byte[8192];
                    while ((readCount = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        writer.Write(buffer, 0, readCount);
                        length += readCount;
                    }
                }
                return "file upload is ok";
            }
    }
    
    //Html
    <head>
        <title></title>
             <meta charset="utf-8" />
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script type="text/javascript">
            function UploadFile() {
                // grab your file object from a file input
                fileData = document.getElementById("fileUpload").files[0];
                var data = new FormData();
                $.ajax({
                    url: 'http://localhost:35508/Service1.svc/FileUpload',
                    type: 'POST',
                    data: fileData,
                    cache: false,
                    dataType: 'json',
                    processData: false, // Don't process the files, Set to false as jQuery will tell the server its a query string request
                    contentType: "application/octet-stream",               
    success: function (data) {
                        alert('successful..');
                    },
                    error: function (data) {
                        alert('Some error Occurred!');
                    }
                });
    
            }
        </script>
    </head>
    <body>
        <div>
            <input type="file" id="fileUpload" value="" />
            <br />
            <br />
            <button id="btnUpload" onclick="UploadFile()">
                Upload
            </button>
        </div>
        <button id="btnDownload" onclick="DownloadFile()">
            Download
        </button>
    </body>
    

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Proposed as answer by Tony---- Tuesday, July 12, 2016 12:58 PM
    • Marked as answer by raysefo Tuesday, July 12, 2016 3:37 PM
    Monday, July 11, 2016 9:01 AM
  • Hi Edward,

    Thanks for your reply. I tried your solution and it worked! You said you are not familiar with ng-img-crop, I need somebody to help me :)

    Best Regards.


    • Edited by raysefo Tuesday, July 12, 2016 8:36 AM
    Tuesday, July 12, 2016 8:35 AM
  • Hi Edward,

    When I crop image with ng-img-crop, it produces 64Bit encoded image. Does the WCF service accept  64Bit encoded image ?

    Best Regards. 

    Wednesday, July 13, 2016 3:56 PM
  • Hi raysefo,

    >> it produces 64Bit encoded image. Does the WCF service accept  64Bit encoded image ?

    Do you mean ng-img-crop pass base64 string to wcf service? If so, you will need to handle this string instead of Stream. You could refer the link below for how to handle base64 string in wcf service.

    # convert base64 string to image in wcf service c#
    http://stackoverflow.com/questions/32666096/convert-base64-string-to-image-in-wcf-service-c-sharp

    If you have any issue about handling base64 string in WCF which is different from your original issue, I would suggest you post a new thread, and then we could focus on this issue.

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, July 15, 2016 5:03 AM