You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何将BLOB转换为Base64编码字符串返回?

问题

我有一个LanguageController类,其中包含如下方法:

@GetMapping("/languages")
public ResponseEntity<List<Language>> getAllLanguages(@RequestParam(required = false) String name) {
    try {
        List<Language> languages = new ArrayList<Language>();

        if (name == null) {
            languageRepository.findAll().forEach(languages::add);
        } else {
            languageRepository.findByNameContaining(name).forEach(languages::add);
        }

        if (languages.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }

        return new ResponseEntity<>(languages, HttpStatus.OK);
    } catch (Exception e) {
        return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Language类定义如下(省略了getter和setter以简化展示):

@Entity
@Table(name = "languages")
public class Language {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

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

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

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

    public Language() {

    }

    public Language(String name, Blob audio, Blob script) {
        this.name = name;
        this.audio = audio;
        this.script = script;
    }
}

调用API接口时,得到如下JSON返回结果:

[
  {
    "id": 1,
    "name": "Test Language",
    "audio": {
      "binaryStream": {},
      "wrappedBlob": {
        "binaryStream": {},
        "traceId": 26,
        "traceObjectName": "blob26"
      }
    },
    "script": {
      "binaryStream": {},
      "wrappedBlob": {
        "binaryStream": {},
        "traceId": 27,
        "traceObjectName": "blob27"
      }
    }
  }
]

目前返回的是BLOB流信息,没有实际使用价值。我希望将BLOB转换为Base64编码后返回,但不清楚应该在哪个环节进行编码处理,恳请提供帮助。

解决方案

推荐优先使用**DTO(数据传输对象)**的方式处理,这是最清晰、符合分层架构的做法,避免直接修改实体类带来的耦合问题。以下是几种可行的实现方式:

方式1:使用DTO转换(推荐)

  1. 创建LanguageDTO类,专门用于向前端返回数据:
public class LanguageDTO {
    private long id;
    private String name;
    private String audioBase64;
    private String scriptBase64;

    // 构造方法、getter、setter
    public LanguageDTO(long id, String name, String audioBase64, String scriptBase64) {
        this.id = id;
        this.name = name;
        this.audioBase64 = audioBase64;
        this.scriptBase64 = scriptBase64;
    }
}
  1. 在Controller中添加转换逻辑,将Language实体转为LanguageDTO并完成Base64编码:
import java.util.stream.Collectors;
import java.util.Base64;
import java.io.InputStream;
import java.io.IOException;
import javax.sql.rowset.serial.SerialBlob;

@GetMapping("/languages")
public ResponseEntity<List<LanguageDTO>> getAllLanguages(@RequestParam(required = false) String name) {
    try {
        List<Language> languages = new ArrayList<>();

        if (name == null) {
            languageRepository.findAll().forEach(languages::add);
        } else {
            languageRepository.findByNameContaining(name).forEach(languages::add);
        }

        if (languages.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }

        // 转换为DTO并处理Base64编码
        List<LanguageDTO> dtoList = languages.stream()
                .map(lang -> new LanguageDTO(
                        lang.getId(),
                        lang.getName(),
                        blobToBase64(lang.getAudio()),
                        blobToBase64(lang.getScript())
                ))
                .collect(Collectors.toList());

        return new ResponseEntity<>(dtoList, HttpStatus.OK);
    } catch (Exception e) {
        return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 工具方法:Blob转Base64
private String blobToBase64(Blob blob) {
    if (blob == null) {
        return null;
    }
    try (InputStream inputStream = blob.getBinaryStream()) {
        byte[] bytes = inputStream.readAllBytes();
        return Base64.getEncoder().encodeToString(bytes);
    } catch (SQLException | IOException e) {
        throw new RuntimeException("Failed to convert Blob to Base64", e);
    }
}

方式2:在实体类中添加转换字段(适合简单场景)

如果不想创建DTO,可以在Language实体中添加用于返回的Base64字段,并忽略原始Blob字段的序列化:

import java.util.Base64;
import java.io.InputStream;
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.Transient;

@Entity
@Table(name = "languages")
public class Language {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

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

    @Column(name = "audio")
    @Lob
    @JsonIgnore // 忽略该字段的JSON序列化
    private Blob audio;

    @Column(name = "script")
    @Lob
    @JsonIgnore // 忽略该字段的JSON序列化
    private Blob script;

    // 不映射到数据库的临时字段,用于返回Base64编码
    @Transient
    private String audioBase64;

    @Transient
    private String scriptBase64;

    // 构造方法、其他字段的getter/setter

    // 获取Base64字段时自动完成转换
    public String getAudioBase64() {
        if (audio == null) return null;
        try (InputStream inputStream = audio.getBinaryStream()) {
            byte[] bytes = inputStream.readAllBytes();
            return Base64.getEncoder().encodeToString(bytes);
        } catch (SQLException | IOException e) {
            throw new RuntimeException("Failed to convert audio Blob to Base64", e);
        }
    }

    public String getScriptBase64() {
        if (script == null) return null;
        try (InputStream inputStream = script.getBinaryStream()) {
            byte[] bytes = inputStream.readAllBytes();
            return Base64.getEncoder().encodeToString(bytes);
        } catch (SQLException | IOException e) {
            throw new RuntimeException("Failed to convert script Blob to Base64", e);
        }
    }
}

此时Controller无需修改,返回的JSON会包含audioBase64和scriptBase64字段,原始Blob字段不会被序列化。

方式3:自定义Jackson序列化器

通过自定义序列化器,让Jackson在序列化实体时自动将Blob转为Base64字符串:

  1. 创建Blob的自定义序列化器:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.util.Base64;
import java.io.InputStream;
import java.io.IOException;

public class BlobBase64Serializer extends JsonSerializer<Blob> {
    @Override
    public void serialize(Blob blob, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (blob == null) {
            gen.writeNull();
            return;
        }
        try (InputStream inputStream = blob.getBinaryStream()) {
            byte[] bytes = inputStream.readAllBytes();
            String base64 = Base64.getEncoder().encodeToString(bytes);
            gen.writeString(base64);
        } catch (SQLException e) {
            throw new IOException("Failed to convert Blob to Base64", e);
        }
    }
}
  1. 在实体类的Blob字段上添加序列化注解:
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@Column(name = "audio")
@Lob
@JsonSerialize(using = BlobBase64Serializer.class)
private Blob audio;

@Column(name = "script")
@Lob
@JsonSerialize(using = BlobBase64Serializer.class)
private Blob script;

这样Controller返回实体类时,Jackson会自动将Blob序列化为Base64字符串。

内容的提问来源于stack exchange,提问作者software_dev_wannabe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:15:26