简体   繁体   中英

Sending Entity Object in Response which contains blob

I am trying to create a springboot usermanagement application.

I have an entity object which contains two blob elements.Here is my entity object.

 @Entity
    @Table(name="user_meta_profile")
    public class UserMetaProfile implements Serializable {
        private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "user_id")
    private int user_id;

    @Column(name = "resume_file")
    @Lob
    private Blob resume_file;

    @Column(name = "photo")
    @Lob
    private Blob photo;

    @Column(name = "username")
    private String username;

    public int getUser_id() {
        return user_id;
    }

    public void setUser_id(int user_id) {
        this.user_id = user_id;
    }

    public Blob getResume_file() {
        return resume_file;
    }

    public void setResume_file(Blob resume_file) {
        this.resume_file = resume_file;
    }

    public Blob getPhoto() {
        return photo;
    }

    public void setPhoto(Blob photo) {
        this.photo = photo;
    }

   public void setUsername(String username) {
        this.username = username;
    }
}

As you can see there are two blob items 'resume_file' and 'photo'.

I want to send back a JSON response to the API call.

My Controller code is as shown below.

 @Controller
    @RequestMapping("/v1")
    public class UsersController {

    @Autowired 
        private IUserMetaProfileService userMetaProfileService;


    @GetMapping("MetaProfile/{id}")
        public ResponseEntity<UserMetaProfile> getUserMetaProfileById(@PathVariable("id") Integer id) {
            UserMetaProfile userMetaProfile = userMetaProfileService.getUsersById(id);
            return new ResponseEntity<UserMetaProfile>(userMetaProfile, HttpStatus.OK);
        }

    }

But when I call the API, I get the exception:

"exception": "org.springframework.http.converter.HttpMessageNotWritableException",

 "message": "Could not write JSON document: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain:
...

   ...nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

Since JSON cannot contain binary data you need to serialize those fields as something else. You have a couple of options:

  1. If you intend to show the binary as an image (since yours is a photo) you can serialize it as a data uri.
  2. Send links to photos instead and create a controller method that will output the binary data with the appropriate content type (beyond the scope here).

So for Option 1 you can do something like this:

@Entity
@Table(name="user_meta_profile")
public class UserMetaProfile implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "user_id")
    private int user_id;

    @Column(name = "resume_file")
    @Lob
    private Blob resume_file;

    @Column(name = "photo")
    @Lob
    private Blob photo;

    @Column(name = "username")
    private String username;

    public int getUser_id() {
        return user_id;
    }

    public void setUser_id(int user_id) {
        this.user_id = user_id;
    }

    @JsonIgnore // disable serializing this field by default
    public Blob getResume_file() {
        return resume_file;
    }

    // serialize as data uri insted
    @JsonProperty("resumeData")
    public String getResume() {
      // just assuming it is a word document. you would need to cater for different media types
      return "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64," + new String(Base64.getEncoder().encode(resume_file.getBytes()));
    }

    public void setResume_file(Blob resume_file) {
        this.resume_file = resume_file;
    }

    @JsonIgnore // disable this one too
    public Blob getPhoto() {
        return photo;
    }

    // serialize as data uri instead
    @JsonProperty("photoData")
    public String getPhotoBase64() {
      // just assuming it is a jpeg. you would need to cater for different media types
      return "data:image/jpeg;base64," + new String(Base64.getEncoder().encode(photo.getBytes()));
    }

    public void setPhoto(Blob photo) {
        this.photo = photo;
    }

   public void setUsername(String username) {
        this.username = username;
    }
}

For the photo bit the value of the photoData JSON attribute can be set directly as the src attribute of an img tag and the photo will be rendered in the HTML. With the resume file you can attach it as an href to a <a> tag with a download attribute so it can be downloaded:

<a href={photoData value here} download>Download Resume File</a>

Just as an FYI if the files are large the JSON will be huge and it might also slow down the browser.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM