Отправка объекта сущности в ответе, который содержит блоб

Я пытаюсь создать приложение Springboot для управления пользователями.

У меня есть объект сущности, который содержит два элемента BLOB-объектов. Вот мой объект сущности.

 @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;
    }
}

Как вы можете видеть, есть два элемента BLOB-объекта: резюме_файла и фото.

Я хочу отправить ответ JSON на вызов API.

Код моего контроллера, как показано ниже.

 @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);
        }

    }

Но когда я вызываю API, я получаю исключение:

"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)

1 ответ

Решение

Поскольку JSON не может содержать двоичные данные, вам нужно сериализовать эти поля как-то еще. У вас есть несколько вариантов:

  1. Если вы намереваетесь показать двоичный файл в виде изображения (поскольку у вас есть фотография), вы можете сериализовать его в виде данных URI.
  2. Вместо этого отправьте ссылки на фотографии и создайте метод контроллера, который будет выводить двоичные данные с соответствующим типом контента (за рамками здесь).

Таким образом, для варианта 1 вы можете сделать что-то вроде этого:

@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;
    }
}

Для фото немного значение photoData Атрибут JSON может быть установлен непосредственно как src атрибут img тег и фото будут отображаться в HTML. С помощью файла резюме вы можете прикрепить его как href к <a> пометить с download атрибут, так что его можно скачать:

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

Также как FYI, если файлы большие, JSON будет огромным, и это может также замедлить работу браузера.

Другие вопросы по тегам