0

enter image description hereI am able to convert image to base 64 string but for some reason when i send it to server i cannot get the original image back here is my code for example if i send an image of size 100kb In server when i decode the image i get only 8 bytes

<html>
<head>
<script src="extensions/angular.min.js"></script>
<script src="bower_components/angular-base64/angular-base64.js"></script>
</head>
<body ng-app="myApp" ng-controller="testcontrol">

    <input type="text" ng-model="A.username" placeholder="Enter Username" required>
    <input type="password" ng-model="A.password" placeholder="Enter Password" required>
    <input type="file" ng-model="B.img" placeholder="Browse image" required>

    <input type="button" value="Send" ng-click="setValues()" />
    <input type="button" value="Send" ng-click="getValues()" />

    <script>


        var app = angular.module('myApp', ['base64']);



        app.controller('testcontrol', function($scope, $http,$base64) {
            $scope.setValues = function() {
                alert("post");

                var a=encodeURIComponent ($base64.encode($scope.B));
               console.log(a);
                $scope.A.image=a;

            console.log(a);
                $http({
                    method : 'POST',
                    url : 'form/post',
                    headers : {
                        'Content-Type' : 'application/json'
                    },
                    data : $scope.A
                }).success(function(data) {


                    alert(JSON.stringify(data));
                });
            };

            $scope.getValues = function() {
                alert("get");
                $http.get('form/get').then(
                        function(response) {
                            if (response) {
                                alert(JSON.stringify(response));
                            }
                        });
            };

        });
    </script>
</body>
</html>

Here is my controller logic

package com.brian.app.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Base64;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.brian.app.dto.TestDto;


@Controller
@RequestMapping(value="/form")
public class Form {
    @ResponseBody
    @RequestMapping(value="/post" ,method=RequestMethod.POST)
    public String save(@RequestBody TestDto test)
    {
logger.info("username"+test.getUsername());
logger.info("password"+test.getPassword());
logger.info("image"+test.getImage());

byte[] decodedValue = Base64.getDecoder().decode(test.getImage());


try {
    FileOutputStream f=new FileOutputStream(new File("/home/shalom/Pictures/tets.png"));

    f.write(decodedValue);
    f.close();

} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}




logger.info("save");    
    return "success";
    }
    @ResponseBody
    @RequestMapping(value="/get" ,method=RequestMethod.POST)
    public String saveget()
    {

logger.info("get"); 
    return "success";
    }
    private static final Logger logger = Logger.getLogger(Form.class);
}

2 Answers2

0

I believe the Base64-encoded image gets truncated because Base64 is not URL-safe. If I were you, I'd move the POST to multipart/formdata:

var fd = new FormData();
fd.append('username', test.getUsername());
fd.append('password', test.getPassword());
fd.append('image', test.getImage());
$http.post('/rest/v1/my/endpoint', fd, {
    transformRequest: angular.identity,
    headers: {'Content-Type': undefined}
})
.success(function(data){
    ...

And then you also need to annotate your spring controller to accept multipart/formdata.

Alternatively, you could URL-encode the Base64 string.

Community
  • 1
  • 1
Johannes Jander
  • 4,974
  • 2
  • 31
  • 46
  • Sir the problem regarding multipart/formdata is that i have lot of images and text data where some images are closely linked with the text the user enters and i would like to have json object because using multipart/formdata it is difficult to map each image for me in my project. –  Feb 24 '16 at 17:27
  • Huh? you can set more than one field in a multipart/form-data POST - like in my answer there are `username`, `password` and `file`. – Johannes Jander Feb 24 '16 at 17:30
  • sir but in the controller side i will have to use multiparthttp request and i cannot use @RequestBody in spring mvc which automatically converts my json to pojo? Sir i am a beginner in spring mvc framework and angular js sir is there any way i can transfer the entire form data as a json object –  Feb 24 '16 at 17:37
  • Sure, just add a JSON object as the only field: `fd.append('json', $scope.A);`. Either that or use `var a=encodeURIComponent ($base64.encode($scope.B));` and stick with `application/x-www-form-urlencoded` – Johannes Jander Feb 24 '16 at 18:04
  • I tried var a=encodeURIComponent ($base64.encode($scope.B)); but it still does not give the actual image original image size 100kb converted images size is 9 bytes image: "dW5kZWZpbmVk" password: "sa" username: "ads" –  Feb 24 '16 at 18:52
  • Sir i am building a e commerce website and my client is very concerned about the performance of the application so in such a case what should i go for base64 or Multipart form? –  Feb 24 '16 at 18:56
  • Doesn't matter, the performance is roughly the same. However if your variable is still truncated after the Url-encode step, you are doing something wrong. Add `console.log (a) ` after `var a=a=encodeURIComponent ($base64.encode($scope.B));` and make a screenshot of the expanded objet on the browser console and add it – Johannes Jander Feb 24 '16 at 19:01
0

Along the lines of what Johannes said about the small size of the base64 string, this line:

var a=encodeURIComponent ($base64.encode($scope.B));

Encodes $scope.B, however your model on the input[type=file] is B.img. I'm not familiar with angular-base64, but should that line be the following?

var a=encodeURIComponent ($base64.encode($scope.B.img));

Sorry for posting this as an answer, not enough reputation to post as a comment on the question.

Steve Wakeford
  • 331
  • 1
  • 8
  • var a=encodeURIComponent ($base64.encode($scope.B.img)); If i try this line i get an error that TypeError: Cannot read property 'img' of undefined –  Feb 24 '16 at 19:50
  • That indicates that $scope.B is undefined. Try changing `` to `ng-model="A.image"` then `var a=encodeURIComponent ($base64.encode($scope.B));` to `var a=encodeURIComponent ($base64.encode($scope.A.image));` and see what gets printed in the console. – Steve Wakeford Feb 24 '16 at 20:08
  • I am able to send it to the server but the value is same as before {username: "adssda", password: "sd", image: "dW5kZWZpbmVk"} image: "dW5kZWZpbmVk" password: "sd" username: "adssda" –  Feb 24 '16 at 20:16
  • After some Googling it seems that ng-model doesn't work with file boxes. Try giving that input an id="myFileInput" and using a line like this: `var a=encodeURIComponent ($base64.encode($('#myFileInput')[0].files[0]));`, see if that shows more in the console. – Steve Wakeford Feb 24 '16 at 20:42
  • ReferenceError: $ is not defined –  Feb 25 '16 at 05:26