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

Quarkus中存储MultipartFormDataInput文件后重新转发的问题

解决Quarkus中Multipart文件存储后转发的二进制内容输出问题

你遇到的核心问题是:Quarkus的REST框架默认会把byte[]的toString()结果(比如[[B@dbe8688)输出到Multipart响应中,而不是把byte数组作为二进制流写入。以下是几种可行的解决方案:

方案一:改用InputStream作为Multipart Part的类型

将存储的byte[]转换为ByteArrayInputStream,框架会自动读取流内容并输出二进制数据:

  1. 修改MyFiles类:
@MultipartForm
public class MyFiles {
    @FormParam("files")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    public List<InputStream> files;

    public MyFiles(List<InputStream> files) {
        this.files = files;
    }

    public MyFiles() {
        files = new ArrayList<>();
    }

    public void add(byte[] fileBytes) {
        files.add(new ByteArrayInputStream(fileBytes));
    }
}
  1. 调整发送文件的方法:
@GET
@Produces(MediaType.MULTIPART_FORM_DATA)
public MyFiles sendStoredFiles() throws IOException {
    MyFiles myFiles = new MyFiles();
    // 遍历从数据库获取的byte[]列表,逐个转成InputStream添加
    for (byte[] fileBytes : getByteArrayFromDataSource()) {
        myFiles.add(fileBytes);
    }
    return myFiles;
}

方案二:自定义MessageBodyWriter处理byte[]序列化

如果必须保留byte[]类型,可以自定义消息体写入器,强制框架将byte数组作为二进制流输出:

@Provider
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public class ByteArrayBodyWriter implements MessageBodyWriter<byte[]> {

    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return byte[].class.isAssignableFrom(type);
    }

    @Override
    public void writeTo(byte[] bytes, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
                        MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
        entityStream.write(bytes);
    }
}

将这个类放在Quarkus能扫描到的包下(比如应用根包),框架会自动使用它来处理byte[]类型的Multipart Part,输出正确的二进制内容。

优化建议:保留文件元数据

实际场景中,转发文件时最好保留原始的文件名、Content-Type等元数据,让接收方更易处理。可以创建一个元数据类存储这些信息:

public class FileMetadata {
    private String filename;
    private String contentType;
    private byte[] content;

    // 构造方法、Getter和Setter
    public FileMetadata(String filename, String contentType, byte[] content) {
        this.filename = filename;
        this.contentType = contentType;
        this.content = content;
    }

    // 省略Getter、Setter
}

读取Multipart时获取元数据:

public FileMetadata getFileMetadata(MultipartFormDataInput input) {
    Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
    List<InputPart> inputParts = uploadForm.get("files");
    if (inputParts == null || inputParts.isEmpty()) return null;
    
    InputPart part = inputParts.get(0);
    // 解析文件名
    String disposition = part.getHeaders().getFirst("Content-Disposition");
    String filename = disposition.split("filename=")[1].replace("\"", "");
    // 获取Content-Type
    String contentType = part.getHeaders().getFirst("Content-Type");
    
    try {
        byte[] content = IOUtils.toByteArray(part.getBody(InputStream.class, null));
        return new FileMetadata(filename, contentType, content);
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

转发时手动构建规范的Multipart响应:

@GET
@Produces(MediaType.MULTIPART_FORM_DATA)
public Response sendStoredFiles() throws IOException {
    List<FileMetadata> fileMetadatas = getFileMetadatasFromDataSource();
    FormDataMultiPart multiPart = new FormDataMultiPart();
    
    for (FileMetadata metadata : fileMetadatas) {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(metadata.getContent());
        // 创建带元数据的Part
        FormDataBodyPart part = new FormDataBodyPart("files", inputStream, 
                MediaType.valueOf(metadata.getContentType()));
        part.setContentDisposition(FormDataContentDisposition.name("files")
                .filename(metadata.getFilename()).build());
        multiPart.bodyPart(part);
    }
    
    return Response.ok(multiPart).build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:50:26