gpt4 book ai didi

cxf - 在 CXF API 中处理多部分附件

转载 作者:行者123 更新时间:2023-12-04 22:14:58 32 4
gpt4 key购买 nike

我正在尝试使用 Apache CXF 开发一个 API 调用,该调用会随请求一起接收附件。我遵循了 this 教程,这就是我到目前为止所得到的。

@POST
@Path("/upload")
@RequireAuthentication(false)
public Response uploadWadl(MultipartBody multipartBody){
List<Attachment> attachments = multipartBody.getAllAttachments();
DataHandler dataHandler = attachments.get(0).getDataHandler();
try {
InputStream is = dataHandler.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return Response("OK");
}

我正在为附件获取一个 InputStream 对象,并且一切正常。但是我需要将附件作为 java.io.File 对象传递给另一个函数。我知道我可以在这里创建一个文件,从输入流中读取并写入它。但是有更好的解决方案吗? CXF 是否已将其存储为文件?如果是这样,我可以继续使用它。有什么建议么?

最佳答案

我也对这个问题很感兴趣。在 CXF 邮件列表上与 Sergey 讨论时,我了解到如果附件超过某个阈值,CXF 将使用临时文件。

在这个过程中,我发现了这个 blogpost,它解释了如何安全地使用 CXF 附件。
您也可以对 this page 上的示例感兴趣。

这就是我目前正在调查中能说的全部内容,我希望能有所帮助。

编辑:目前这里是我们如何使用 CXF 2.6.x 处理附件。关于使用多部分内容类型上传文件。

在我们的 REST 资源中,我们定义了以下方法:

  @POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/")
public Response archive(
@Multipart(value = "title", required = false) String title,
@Multipart(value = "hash", required = false) @Hash(optional = true) String hash,
@Multipart(value = "file") @NotNull Attachment attachment) {

...

IncomingFile incomingFile = attachment.getObject(IncomingFile.class);

...
}

关于该片段的一些说明:
  • @Multipart 不是 JAXRS 的标准,它甚至不在 JAXRS 2 中,它是 CXF 的一部分。
  • 在我们的代码中,我们实现了 bean 验证(您必须在 JAXRS 1 中自己完成)
  • 您不必使用 MultipartBody ,这里的关键是使用 Attachment
  • 类型的参数

    所以是的,据我们所知,目前还不可能在方法签名中直接获取我们想要的类型。因此,例如,如果您只想要附件的 InputStream,则不能将其放在方法的签名中。您必须使用 org.apache.cxf.jaxrs.ext.multipart.Attachment 类型并编写以下语句:

    InputStream inputStream = attachment.getObject(InputStream.class);

    我们还发现在 Sergey Beryozkin 的帮助下,我们可以转换或包装这个 InputStream ,这就是为什么在上面的代码片段中我们写道:

    IncomingFile incomingFile = attachment.getObject(IncomingFile.class);
    IncomingFile 是我们围绕 InputStream 的自定义包装器,为此您必须注册 MessageBodyReaderParamHandler 将无济于事,因为它们不适用于流,但可以使用 String

    @Component
    @Provider
    @Consumes
    public class IncomingFileAttachmentProvider implements MessageBodyReader<IncomingFile> {
    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    return type != null && type.isAssignableFrom(IncomingFile.class);
    }

    @Override
    public IncomingFile readFrom(Class<IncomingFile> type,
    Type genericType,
    Annotation[] annotations,
    MediaType mediaType,
    MultivaluedMap<String, String> httpHeaders,
    InputStream entityStream
    ) throws IOException, WebApplicationException {

    return createIncomingFile(entityStream, fixedContentHeaders(httpHeaders)); // the code that will return an IncomingFile
    }
    }

    但是请注意,已经进行了一些尝试以了解通过什么、如何以及热修复错误的方式(例如,附件部分的第一个标题的第一个字母是eat,因此您使用的是 ontent-Type 而不是 Content-Type )。

    当然 entityStream 代表附件的实际 InputStream。此流将从内存或磁盘读取数据,具体取决于 CXF 放置数据的位置;有一个大小阈值属性( attachment-memory-threshold )。您还可以说明临时附件的去向 ( attachment-directory )。

    完成后不要忘记 关闭流 (某些工具会为您完成)。

    一切都配置好后,我们使用 Johan Haleby 的 Rest-Assured 对其进行了测试。 (虽然有些代码是我们测试工具的一部分):

    given().log().all()
    .multiPart("title", "the.title")
    .multiPart("file", file.getName(), file.getBytes(), file.getMimeType())
    .expect().log().all()
    .statusCode(200)
    .body("store_event_id", equalTo("1111111111"))
    .when()
    .post(host().base().endWith("/store").toStringUrl());

    或者,如果您需要以这种方式通过 curl 上传文件:
    curl --trace -v -k -f
    --header "Authorization: Bearer b46704ff-fd1d-4225-9dd4-e29065532b73"
    --header "Content-Type: multipart/form-data"
    --form "hash={SHA256}3e954efb149aeaa99e321ffe6fd581f84d5a497b6fab5c86e0d5ab20201f7eb5"
    --form "title=fantastic-video.mp4"
    --form "archive=@/the/path/to/the/file/fantastic-video.mp4;type=video/mp4"
    -X POST http://localhost:8080/api/video/event/store

    为了完成这个答案,我想提一下,可以在多部分中使用 JSON 有效负载,为此您可以在签名中使用 Attachment 类型,然后编写

    Book book = attachment.getObject(Book.class)

    或者你可以写一个像这样的论点:

    @Multipart(value="book", type="application/json") Book book

    只是不要忘记在执行请求时将 Content-Type header 添加到相关部分。

    值得一提的是,可以将所有部分都放在一个列表中,只需编写一个具有 List<Attachment> 类型的单个参数的方法。但是,我更喜欢在方法签名中包含实际参数,因为它更简洁,样板更少。

    @POST
    void takeAllParts(List<Attachment> attachments)

    关于cxf - 在 CXF API 中处理多部分附件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10801122/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com