骆驼Rest DSL检索HTTP POST多部分文件

4

以下是我的路由器类,我正试图上传视频文件并将其存储到一个文件位置。

SpringBootRouter.java

package com.camelrest;

import java.util.HashMap;
import java.util.Map;

import org.apache.camel.component.restlet.RestletComponent;
import org.apache.camel.spring.boot.FatJarRouter;
import org.restlet.Component;
import org.restlet.ext.spring.SpringServerServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class MySpringBootRouter extends FatJarRouter {

    @Autowired
    private MultipartProcessor multipartProcessor;

    @Override
    public void configure() {

        restConfiguration().component("restlet");

        rest("/upload").post().to("direct:upload");

        from("direct:upload")
        .to("file://E:/RestTest");

    }

    @Bean
    public ServletRegistrationBean servletRegistrationBean() {

        SpringServerServlet serverServlet = new SpringServerServlet();
        ServletRegistrationBean regBean = new ServletRegistrationBean(
                serverServlet, "/rest/*");

        Map<String, String> params = new HashMap<String, String>();

        params.put("org.restlet.component", "restletComponent");

        regBean.setInitParameters(params);

        return regBean;
    }

    @Bean
    public Component restletComponent() {
        return new Component();
    }

    @Bean
    public RestletComponent restletComponentService() {
        return new RestletComponent(restletComponent());
    }    
}

我正在尝试使用Postman上传视频文件,如下屏幕截图所示:

enter image description here

我上传的文件内容被保存为具有由camel生成的随机驼峰ID的文件名

enter image description here

然而,我想要传递在正文中的文件名

SampleVideo_1280x720_10mb.mp4

作为文件名,并从正文中删除以下内容

----------------------------948281627232093197119960
Content-Disposition: form-data; name="file"; filename="SampleVideo_1280x720_10mb.mp4"
Content-Type: video/mp4

所以最终输出可以是使用在Postman上传时使用的文件名上传的视频。

你需要创建一个bean或处理器来提取名称。尝试查看commons fileupload https://commons.apache.org/proper/commons-fileupload/streaming.html。 - Aku Nour
2个回答

8
您可以使用MimeMultipartDataFormat来反序列化多部分请求。这样做将准备附件,以便Exchange
之后,您需要以某种方式将Attachment转换为InputStream并填充CamelFileName头。对于此任务,小的Processor可以帮助您。 路由:
from("direct:upload")
        .unmarshal().mimeMultipart().split().attachments()
        .process(new PrepareFileFromAttachment())
        .to("file://C:/RestTest");

处理器:
class PrepareFileFromAttachment implements Processor {
    @Override
    public void process(Exchange exchange) throws Exception {
        DataHandler dataHandler = exchange.getIn().getBody(Attachment.class).getDataHandler();
        exchange.getIn().setHeader(Exchange.FILE_NAME, dataHandler.getName());
        exchange.getIn().setBody(dataHandler.getInputStream());
    }
}

上述方法对于表单中只包含单个输入的情况不起作用。这是因为MimeMultipartDataFormat将第一个表单输入转换为主体(不存储文件名),而将其他输入转换为附件,其中存储了文件名。 在这种情况下,您需要创建一个读取InputStreamProcessor

路线:

from("direct:upload")
        .process(new ProcessMultipartRequest())
        .to("file:c://RestTest");

Processor

public class ProcessMultipartRequest implements Processor {
    @Override
    public void process(Exchange exchange) throws Exception {
        InputStream is = exchange.getIn().getBody(InputStream.class);
        MimeBodyPart mimeMessage = new MimeBodyPart(is);
        DataHandler dh = mimeMessage.getDataHandler();
        exchange.getIn().setBody(dh.getInputStream());
        exchange.getIn().setHeader(Exchange.FILE_NAME, dh.getName());
    }
}

感谢您的见解。 当我在这一行放置调试器时,.attachments()返回null: DataHandler dataHandler = exchange.getIn().getBody(Attachment.class).getDataHandler(); 返回null。您能否建议其他获取文件名的方法?现在,body设置了视频,我能够在Postman中看到视频,但无法获取上传视频的文件名。请建议我解决方法。 - Vikram
我明白了。这种方法只适用于您的帖子在Postman中包含任何其他表单键的情况下。当表单提交仅包含文件键时,它会直接编组到正文中,而不是作为附件。我正在调试“MimeMultipartDataFormat”中发生了什么。 - Bedla
调试后,我发现请求的第一部分始终存储在“body”中,在这种情况下,文件名丢失。它仅存储到附件的其他键中。我已经编辑了答案,并提供了单键表单的解释和替代实现。 - Bedla
非常棒的答案,我曾经为此苦苦挣扎,非常感谢。如果我们需要处理多个键(例如上传文件并在正文中传递其他值),您能否对多部分数据进行一些解释?那也会非常有帮助... - Vikram

0
在multipart/form-data请求中,字段的顺序很重要。在提交时,文件字段应该是第一个。Apache Camel会为请求中除第一个字段外的所有字段创建附件对象。
例如: Multipart Form data Postman请求 其他字段:
- var1和var2会成为附件对象。

    from(route)
        .unmarshal().mimeMultipart().split().attachments()
        .log("process")
        .end()
        .process(new MyProcessor())
        .end();



    public class MyProcessor implements Processor {
        @Override
        public void process(Exchange exchange) throws Exception {
            // Other field values
            Collection<Attachment> attachments = exchange.getIn().getAttachmentObjects().values();
            for(Attachment attachment : attachments){
                // attachment value
                attachment.getDataHandler().getInputStream();
            }
            // Body of request file content
            InputStream is = exchange.getIn().getBody(InputStream.class);
        }
    }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接