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

Spring RestTemplate向邮件API发送byte[]数据异常问题解决

解决RestTemplate调用邮件API时byte[]字段序列化问题

问题场景

调用邮件API时,使用Spring的RestTemplate发送请求始终失败,但将HttpEntity的body内容复制到Postman中却能正常请求。尝试自定义实体类的toString方法匹配Postman的请求格式,仍然无效,最终定位问题出在content字段的byte[]数据序列化上。

相关代码

实体类CreateAndQueueMailRq

@Builder
public class CreateAndQueueMailRq {
private String application;
private String bcc;
private String body;
private String cc;
private String creationDate;
private String creationUser;
private String from;
private String fromName;
private String id;
private String market;
private String subject;
private String system;
private String to;
private String language;
private String type;
private String attachmentType;
private String attachmentFileName;
private byte[] content;

@Override
public String toString() {
    return "{\"application\":\"" + application + "\","
            + "\"bcc\":\"" + bcc + "\","
            + "\"body\":\"" + body + "\","
            + "\"cc\":\"" + cc + "\","
            + "\"creationDate\":\"" + creationDate + "\","
            + "\"creationUser\":\"" + creationUser + "\","
            + "\"from\":\"" + from + "\","
            + "\"fromName\":\"" + fromName + "\","
            + "\"id\":\"" + id + "\","
            + "\"market\":\"" + market + "\","
            + "\"subject\":\"" + subject + "\","
            + "\"system\":\"" + system + "\","
            + "\"to\":\"" + to + "\","
            + "\"language\":\"" + language + "\","
            + "\"type\":\"" + type + "\","
            + "\"attachmentType\":\"" + attachmentType + "\","
            + "\"attachmentFileName\":\"" + attachmentFileName + "\","
            + "\"content\":" + Arrays.toString(content) + "}";
}
}

请求调用代码

public boolean sendMailWithAttachment(String body, String from, String fromName,
                                      String id, String subject, String to, String language,
                                      String filename, byte[] content, String cc, String bcc){

    CreateAndQueueMailRq createAndQueueMailRq = CreateAndQueueMailRq.builder()
            .application("appname")
            .bcc("")
            .body(body)
            .cc("samplemail@gmail.com")
            .creationDate(LocalDateTime.now().format(FORMATTER))
            .creationUser(MailManagerConstants.COMING2)
            .from(from)
            .fromName(fromName)
            .id(id)
            .market("market_default")
            .subject(subject)
            .system("system_default")
            .to("samplemail@gmail.com")
            .language("ES")
            .type(DEFAULT_TYPE)
            .attachmentType(MailManagerConstants.TYPE_PDF)
            .attachmentFileName(filename)
            .content(content)
            .build();

    return generateRequest(createAndQueueMailRq, API_MAIL_MANAGER_WITH_ATTACHMENT);
}

private boolean generateRequest(CreateAndQueueMailRq createAndQueueMailRq, String api) {
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    try {
        HttpEntity<CreateAndQueueMailRq> request = new HttpEntity<>(createAndQueueMailRq, headers);
        System.out.println("Request: "+request.getBody());
        ResponseEntity<?> response = restTemplate.exchange(api, HttpMethod.POST, request, String.class);
        LOGGER.info(SUCCESS_MESSAGE);
        return true;
    }catch (HttpClientErrorException e){
        LOGGER.info("STATUS CODE: "+e.getStatusCode());
        LOGGER.info("RESPONSE BODY: "+e.getResponseBodyAsString());
        LOGGER.info(ERROR_MESSAGE);
        return false;
}
}

问题分析

默认的序列化逻辑会将byte[]类型的content字段转换为带双引号的字符串格式(如"content":"[37,40,30...]"),但目标API需要的是不带引号的纯数组格式(如"content":[37,40,30...]),这就导致RestTemplate发送的请求格式不符合API要求,而Postman中使用的是正确格式,因此可以成功调用。

解决方案:自定义HttpMessageConverter

通过继承GsonHttpMessageConverter并自定义序列化逻辑,对byte[]类型单独处理,输出API需要的格式:

public class MailManagerCustomConverter extends GsonHttpMessageConverter {

    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        if (object instanceof byte[]) {
            byte[] bytes = (byte[]) object;
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (int i = 0; i < bytes.length; i++) {
                if (i > 0) {
                    sb.append(",");
                }
                sb.append(bytes[i]);
            }
            sb.append("]");
            outputMessage.getBody().write("\"content\":".getBytes());
            outputMessage.getBody().write(sb.toString().getBytes());
        } else {
            super.writeInternal(object, outputMessage);
        }
}
}

该转换器会将content字段输出为"content":[37,40,30...]格式,而非默认的带引号字符串格式,从而符合API的请求要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:32:17