0

I have a class of Achievement with an image which is byte[].

@Entity
@Table(name = "ACHIEVEMENT")
public class Achievement {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long achievementId;
private byte[] image;

THe problem is that the user send an image URL to the endpoint of create

{
    "image": "https://img.favpng.com/13/18/21/computer-icons-achievement-trophy-award-png-favpng-TYahJ0mkcwhJYqA1BPqKcSibe.jpg",
}


    public ResponseEntity<?> createAchievement(@RequestBody Achievement achievement)

Spring throws error when reading the request body and doesn't even allow me to convert the image to a byte array.

JSON parse error: Cannot deserialize value of type byte[] from String "//img.favpng.com/13/18/21/computer-icons-achievement-trophy-award-png-favpng-TYahJ0mkcwhJYqA1BPqKcSibe.jpg": Failed to decode VALUE_STRING as base64 (MIME-NO-LINEFEEDS): Illegal character ':' (code 0x3a) in base64 content;

What can I do to allow the String to be passed to the endpoint so I can convert to a byte array?

user12361681
  • 97
  • 2
  • 7
  • check out base64 encoding.. https://stackoverflow.com/questions/20706783/put-byte-array-to-json-and-vice-versa – jackycflau Mar 03 '20 at 10:24
  • 2
    What do you want to store? Image URL or actual image data? – Lesiak Mar 03 '20 at 10:26
  • 1
    As jackycflau said either have your front-end encode the file as base64 or handle the url separately, i.e. let the user provide the url and have the server download the image (beware of security issues though). – Thomas Mar 03 '20 at 10:26
  • I want to store the image data – user12361681 Mar 03 '20 at 10:26
  • Don't use Achievement entity in your controller.. Create new model class, to get image url as string. Then map it to your entity class by fetching actual image data. And then save in the database, though its recommended to store image url in db rather than actual image. – AmitB10 Mar 03 '20 at 10:33

3 Answers3

0

The best way to achieve that is to create "CreateAchievementCommand" class, which will be DTO between your endpoint and service logic (btw. waiting for entity object as the request body is usually really bad, please read more about why we use DTO). It could contain all the properties from Achievement, except image property, that should be String (the URL is the string).

Then you should convert your CreateAchievementCommand into Achievement, and use Http client (WebFlux, or RestTemplate (deprecated from spring version > 5.0) to fetch the image from URL and save it as a byte array.

B_Osipiuk
  • 888
  • 7
  • 16
0

The problem is that in your Achievement class you have defined "image" type as "byte" but in json request "image" type is String.

You have to change "image" type to String in Achievement Class and then decode it.

0

You need to download the image first. Spring can't know that it should use the given String as location from where to download the actual image date. You could create a simple method that downloads the image data as follows:

    public byte[] getImageDate(String url) {
        return new RestTemplate().getForEntity(url, byte[].class).getBody();
    }
times29
  • 2,782
  • 2
  • 21
  • 40