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

Jersey REST服务接收多部分请求时字节被替换问题

解决Jersey 2.25.1 + Tomcat7 非文本文件上传字节被替换的问题

我之前做文件上传功能时也踩过一模一样的坑!你遇到的D2被替换成EF BF BD(也就是Unicode替换字符�)的问题,本质是二进制数据被错误当成文本流做字符编码解析了。docx、pdf这类非文本文件的字节序列本来就不符合UTF-8等文本编码规则,解码器碰到无法识别的字节就会用替换字符兜底,直接导致文件损坏。给你几个具体的解决步骤:

1. 绝对不要用字符串接收二进制文件内容

很多人会下意识用getBodyAsString()获取文件内容,但这会强制Jersey把字节流按默认字符编码(通常是UTF-8)解码成字符串,这对非文本文件来说完全是错误操作。

错误示例:

// 这种写法会导致二进制字节被错误解码
String fileContent = filePart.getBodyAsString();

正确写法:直接用InputStream或byte[]接收二进制流:

InputStream fileStream = filePart.getBody(InputStream.class);
// 或者直接获取字节数组
byte[] fileBytes = filePart.getBody(byte[].class);

2. 明确指定二进制媒体类型

在获取文件内容时,显式指定媒体类型为APPLICATION_OCTET_STREAM,告诉Jersey这是纯二进制数据,不要做任何字符转换:

InputStream fileStream = filePart.getBody(InputStream.class, MediaType.APPLICATION_OCTET_STREAM_TYPE);

3. 检查Jersey Multipart配置是否正确

确保你已经正确引入jersey-media-multipart依赖,并且在ResourceConfig或Application类中注册了MultiPartFeature:

public class MyRestApplication extends ResourceConfig {
    public MyRestApplication() {
        // 必须注册这个Feature才能处理multipart请求
        register(MultiPartFeature.class);
        // 注册你的资源类
        register(UploadResource.class);
    }
}

4. 完整的上传方法示例

给你一个可以直接参考的完整实现,确保全程用字节流处理文件:

@Path("/files")
public class UploadResource {

    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(
            @FormDataParam("file") FormDataBodyPart filePart,
            @FormDataParam("file") FormDataContentDisposition fileDisposition) {

        // 获取文件名和输入流
        String fileName = fileDisposition.getFileName();
        InputStream inputStream = filePart.getBody(InputStream.class, MediaType.APPLICATION_OCTET_STREAM_TYPE);

        // 保存文件到本地(替换成你的存储逻辑)
        try (FileOutputStream fos = new FileOutputStream("/your/save/path/" + fileName)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                    .entity("Failed to save file: " + e.getMessage())
                    .build();
        }

        return Response.ok("File uploaded successfully: " + fileName).build();
    }
}

额外排查点:Tomcat编码配置

虽然核心问题在Jersey的处理方式,但也可以检查下Tomcat7的server.xml中Connector的编码设置,确保没有强制对请求体做不必要的编码转换。比如不要设置useBodyEncodingForURI="true",URIEncoding="UTF-8"是没问题的,它只影响URI的编码,不会干扰multipart请求体的解析。

按照上面的步骤调整后,非文本文件的字节应该就能完整保留了,不会再出现替换字符的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:23:05