文件上传以及Jersey restful web服务中的其他对象 [英] File upload along with other object in Jersey restful web service

查看:155
本文介绍了文件上传以及Jersey restful web服务中的其他对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过上传图片和员工数据来在系统中创建员工信息。我可以使用球衣进行不同的休息呼叫。但我希望在一次休息电话中实现。
我在结构下方提供。请帮我解决这方面的问题。

I want to create an employee information in the system by uploading an image along with employee data. I am able to do it with different rest calls using jersey. But I want to achieve in one rest call. I provide below the structure. Please help me how to do in this regard.

@POST
@Path("/upload2")
@Consumes({MediaType.MULTIPART_FORM_DATA,MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response uploadFileWithData(
        @FormDataParam("file") InputStream fileInputStream,
        @FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
        Employee emp) {

//..... business login

}

每当我想要做的时候,我都会在Chrome邮递员中出错。我的Employee json的简单结构如下所示。

Whenever I am trying to do, I get error in Chrome postman. The simple structure of my Employee json is given below.

{
    "Name": "John",
    "Age": 23,
    "Email": "john@gmail.com",
    "Adrs": {
        "DoorNo": "12-A",
        "Street": "Street-11",
        "City": "Bangalore",
        "Country": "Karnataka"
    }
}

但是我可以通过进行两次不同的调用来实现,但我希望在一次休息调用中实现,以便我可以接收文件以及该员工的实际数据。

However I can do it by making two different call, but I want to achieve in one rest call so that I can receive the file as well as the actual data of the employee.

请求您提供这方面的帮助。

Request you to help in this regard.

推荐答案

你不能有两个 Content-Type (从技术上来说,这就是我们在下面所做的,但是它们与每个部分分开multipart,但主要类型是multipart)。这基本上就是你对你的方法所期望的。您期望将mutlipart json一起作为主要媒体类型。 Employee 数据需要成为multipart的一部分。因此,您可以为员工添加 @FormDataParam(emp)

You can't have two Content-Types (well technically that's what we're doing below, but they are separated with each part of the multipart, but the main type is multipart). That's basically what you are expecting with your method. You are expecting mutlipart and json together as the main media type. The Employee data needs to be part of the multipart. So you can add a @FormDataParam("emp") for the Employee.

@FormDataParam("emp") Employee emp) { ...

以下是我用于测试的课程

Here's the class I used for testing

@Path("/multipart")
public class MultipartResource {

    @POST
    @Path("/upload2")
    @Consumes({MediaType.MULTIPART_FORM_DATA})
    public Response uploadFileWithData(
            @FormDataParam("file") InputStream fileInputStream,
            @FormDataParam("file") FormDataContentDisposition cdh,
            @FormDataParam("emp") Employee emp) throws Exception{

        Image img = ImageIO.read(fileInputStream);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img)));
        System.out.println(cdh.getName());
        System.out.println(emp);

        return Response.ok("Cool Tools!").build();
    } 
}

首先我刚用客户端API测试以确保它工作

First I just tested with the client API to make sure it works

@Test
public void testGetIt() throws Exception {

    final Client client = ClientBuilder.newBuilder()
        .register(MultiPartFeature.class)
        .build();
    WebTarget t = client.target(Main.BASE_URI).path("multipart").path("upload2");

    FileDataBodyPart filePart = new FileDataBodyPart("file", 
                                             new File("stackoverflow.png"));
    // UPDATE: just tested again, and the below code is not needed.
    // It's redundant. Using the FileDataBodyPart already sets the
    // Content-Disposition information
    filePart.setContentDisposition(
            FormDataContentDisposition.name("file")
                                    .fileName("stackoverflow.png").build());

    String empPartJson
            = "{"
            + "  \"id\": 1234,"
            + "  \"name\": \"Peeskillet\""
            + "}";

    MultiPart multipartEntity = new FormDataMultiPart()
            .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
            .bodyPart(filePart);

    Response response = t.request().post(
            Entity.entity(multipartEntity, multipartEntity.getMediaType()));
    System.out.println(response.getStatus());
    System.out.println(response.readEntity(String.class));

    response.close();
}

我刚刚创建了一个简单的员工具有 id name 字段的类,用于测试。这完全没问题。它显示图像,打印内容处理,并打印 Employee 对象。

I just created a simple Employee class with an id and name field for testing. This works perfectly fine. It shows the image, prints the content disposition, and prints the Employee object.

我不太熟悉和邮差一起,所以我保存了最后的测试: - )

I'm not too familiar with Postman, so I saved that testing for last :-)

它似乎工作正常,因为你可以看到响应酷工具。但是如果我们查看打印的 Employee 数据,我们会看到它为空。这很奇怪,因为使用客户端API它工作正常。

It appears to work fine also, as you can see the response "Cool Tools". But if we look at the printed Employee data, we'll see that it's null. Which is weird because with the client API it worked fine.

如果我们查看预览窗口,我们会看到问题

If we look at the Preview window, we'll see the problem

\\ temp 正文部分没有 Content-Type 标头。您可以在客户端API中看到我明确设置它

There's no Content-Type header for the emp body part. You can see in the client API I explicitly set it

MultiPart multipartEntity = new FormDataMultiPart()
        .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
        .bodyPart(filePart);

所以我想这只是部分的完整答案。就像我说的,我不熟悉Postman所以我不知道如何为个人身体部位设置 Content-Type 。我为图像部分自动设置了图像的图像/ png (我猜它只是由文件扩展名决定)。如果你能解决这个问题,那么问题就应该解决了。如果您发现如何做到这一点,请将其作为答案发布。

So I guess this is really only part of a full answer. Like I said, I am not familiar with Postman So I don't know how to set Content-Types for individual body parts. The image/png for the image was automatically set for me for the image part (I guess it was just determined by the file extension). If you can figure this out, then the problem should be solved. Please, if you find out how to do this, post it as an answer.

  • See here for more about MultiPart with Jersey.

基本配置:

依赖关系:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>${jersey2.version}</version>
</dependency>

客户配置:

final Client client = ClientBuilder.newBuilder()
    .register(MultiPartFeature.class)
    .build();

服务器配置:

// Create JAX-RS application.
final Application application = new ResourceConfig()
    .packages("org.glassfish.jersey.examples.multipart")
    .register(MultiPartFeature.class);






更新



从Postman客户端可以看出,一些客户端在使用 FormData <时,无法设置单个部件的Content-Type,包括浏览器的默认功能/ code>(js)。


UPDATE

So as you can see from the Postman client, some clients are unable to set individual parts' Content-Type, this includes the browser, in regards to it's default capabilities when using FormData (js).

我们不能指望客户找到这个,所以我们可以做的是,在接收数据时,在反序列化之前显式设置Content-Type。例如

We can't expect the client to find away around this, so what we can do, is when receiving the data, explicitly set the Content-Type before deserializing. For example

@POST
@Path("upload2")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@FormDataParam("emp") FormDataBodyPart jsonPart,
                                  @FormDataParam("file") FormDataBodyPart bodyPart) { 
     jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
     Employee emp = jsonPart.getValueAs(Employee.class);
}

获得POJO需要额外的工作,但这是一个更好的解决方案而不是强迫客户尝试找到它自己的解决方案。

It's a little extra work to get the POJO, but it is a better solution than forcing the client to try and find it's own solution.


  • 这些评论中有一条您可能感兴趣的对话正在使用与默认HttpUrlConnection不同的连接器。

  • There is a conversation in these comments that you may be interested in if you are using a different Connector than the default HttpUrlConnection.

这篇关于文件上传以及Jersey restful web服务中的其他对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆