使用Jersey发送多个文件:找不到multipart / form-data的MessageBodyWriter [英] Sending multiple files with Jersey: MessageBodyWriter not found for multipart/form-data

查看:153
本文介绍了使用Jersey发送多个文件:找不到multipart / form-data的MessageBodyWriter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是java rest应用程序的新手。
我正在尝试运行一个应用程序,但我有这个例外

I'm new in java rest application. I'm trying to run an application, but i have this exception

message com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class java.util.ArrayList, and MIME media type, multipart/form-data, was not found

exception
com.sun.jersey.api.client.ClientHandlerException: com.sun.jersey.api.client.ClientHandlerException: A message body writer for Java type, class java.util.ArrayList, and MIME media type, multipart/form-data, was not found
com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:155)
com.sun.jersey.api.client.Client.handle(Client.java:652)
com.sun.jersey.api.client.WebResource.handle(WebResource.java:682)
com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:570)
org.eu.paas.client.APIClient.doPost(APIClient.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)

APIClient.java:265 我有类似的事情:

cr = service.path(path)
    .type(MediaType.MULTIPART_FORM_DATA)
    .post(ClientResponse.class, listForm);

其中 listForm ArrayList< InputStream>

在剩下的应用程序中我有:

and in the rest application I have:

@POST
@Path("{appId-appId}/action/Multideploy/env/{envId-envId}")
@Consumes(MediaType.MULTIPART_FORM_DATA)    
@Produces(MediaType.APPLICATION_XML)
Response MultideployApplication(
        @PathParam("appId-appId") String appid, @PathParam("envId-envId") String envid,
        @FormDataParam("file") List<InputStream> uploadedInputStream);

同样在我的pom.xml中我有这些依赖项:

Also in my pom.xml I have these dependencies:

<dependencies>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-server</artifactId>
        <version>1.8</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-multipart</artifactId>
        <version>1.18</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-client</artifactId>
        <version>1.19</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>


推荐答案

Jersey使用 MessageBodyWriter 用于处理将Java对象序列化为请求流(或服务器端的响应流,以及 MessageBodyReader 来处理 de - 将响应流(或服务器端的请求流)串行化为Java对象。您可以在 JAX-RS实体提供商

Jersey uses MessageBodyWriters to handle serialization of Java objects to the request stream (or response stream on server side, and MessageBodyReaders to handle de-serialization of the response stream (or request stream on server side) into Java objects. You can read more at JAX-RS Entity Providers.

这就是说,每当你看到像No MessageBodyReader(Writer)这样的错误时找到类型所以和java类型一样,这意味着没有序列化器来处理转换。在你的特殊情况下,它是说没有编写器可以处理转换 ArrayList 到multipart / form-data。这是有道理的,因为作者将如何知道如何进行此转换。

That being said, whenever you see an error like "No MessageBodyReader(Writer) found for type so and so and java type so and so", it means that there is no serializer to handle the conversion. In you particular case, it is saying that there is not writer that can handle the conversion of an ArrayList to multipart/form-data. This makes sense, as how will the writer know how to make this conversion.

对于multipart,你需要实际上你在客户端客户端上的多部分API。作者知道如何将这些API对象转换为所需的多部分。有关API的完整列表,您可以查看包 com.sun.jersey.multipart

For multipart, you need to actually use the multipart APIs on the client client side. The writer knows how to convert these API object into the required multipart parts. For the complete list of APIs, you can look at the package com.sun.jersey.multipart.

以下是发送文件的示例

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public String getTest(@FormDataParam("file") InputStream in,
                      @FormDataParam("file") FormDataContentDisposition fdc) {
    try (FileOutputStream out = new FileOutputStream(fdc.getFileName())) {
        ReaderWriter.writeTo(in, out);
    } catch (IOException ex) {
        ex.printStackTrace(System.out);
        return "Bad $#!t happended";
    }
    return "Upload OK";
}

@Test
public void doit() {
    File file = new File("...");
    FileDataBodyPart filePart = new FileDataBodyPart("file", file);
    MultiPart entity = new FormDataMultiPart()
            .bodyPart(filePart);
    Client client = Client.create();
    WebResource resource = client.resource("http://localhost:9998/service");
    ClientResponse response = resource
            .type(MediaType.MULTIPART_FORM_DATA_TYPE)
            .post(ClientResponse.class, entity);
    assertEquals(200, response.getStatus());
    assertEquals("Upload OK", response.getEntity(String.class));
    response.close();
}

目前还没有针对Jersey multipart的1.x支持的文档。但很多时候,测试中都会看到最好的文档。因此,如果您想要更多示例,查看针对jersey-multipart的测试

There's really no documentation for the 1.x support for Jersey multipart. But a lot of times, the best documentation is seen in the tests. So if you want some more examples to go off of, look at the tests for jersey-multipart.

这是一个使用Jersey Test Framework的完整测试。像任何其他JUnit测试一样运行它。使用系统上某些任意文件的位置替换常量 FILE_ONE FILE_TWO 。您应该看到保存到当前工作目录的文件(很可能是项目根目录)

Here is a complete test using Jersey Test Framework. Run it like any other JUnit test. Replace the constants FILE_ONE and FILE_TWO with the location of some arbitrary files on your system. You should see the files saved to your current working directory (most likely the project root)

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.core.DefaultResourceConfig;
import com.sun.jersey.core.header.ContentDisposition;
import com.sun.jersey.core.util.ReaderWriter;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.FormDataParam;
import com.sun.jersey.multipart.MultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
import com.sun.jersey.spi.container.servlet.WebComponent;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import static org.junit.Assert.assertEquals;
import org.junit.Test;

/**
 * Run this like any other JUnit test. Dependencies for test are as follows.
 * 
 * <jersey.version>1.19</jersey.version>
 * 
 * <dependency>
 *    <groupId>com.sun.jersey</groupId>
 *    <artifactId>jersey-servlet</artifactId>
 *    <version>${jersey.version}</version>
 * </dependency>
 * <dependency>
 *    <groupId>com.sun.jersey</groupId>
 *    <artifactId>jersey-servlet</artifactId>
 *    <version>${jersey.version}</version>
 * </dependency>
 * <dependency>
 *    <groupId>com.sun.jersey.jersey-test-framework</groupId>
 *    <artifactId>jersey-test-framework-grizzly2</artifactId>
 *    <version>1.19</version>
 *    <scope>test</scope>
 * </dependency>
 * <dependency>
 *    <groupId>com.sun.jersey.contribs</groupId>
 *    <artifactId>jersey-multipart</artifactId>
 *    <version>${jersey.version}</version>
 * </dependency>
 * 
 */
public class MultipartTest extends JerseyTest {


    @Path("service")
    public static class Service {

        @POST
        @Consumes(MediaType.MULTIPART_FORM_DATA)
        @Produces(MediaType.TEXT_PLAIN)
        public String getTest(@FormDataParam("file") List<FormDataBodyPart> files) {
            for (FormDataBodyPart filePart: files) {
                ContentDisposition cd = filePart.getContentDisposition();
                try (FileOutputStream out = new FileOutputStream(cd.getFileName())) {
                    ReaderWriter.writeTo(filePart.getEntityAs(InputStream.class), out);
                } catch (IOException ex) {
                    ex.printStackTrace(System.out);
                    return "Oops";
                }
            }
            return "Upload OK";
        }
    }

    public static class AppConfig extends DefaultResourceConfig {
        public AppConfig() {
            super(Service.class);
        }
    }

    @Override
    public WebAppDescriptor configure() {
        return new WebAppDescriptor.Builder()
                .initParam(WebComponent.RESOURCE_CONFIG_CLASS, 
                           AppConfig.class.getName())
                .build();
    }

    private static final String FILE_ONE = "<enter-a-file-path>";
    private static final String FILE_TWO = "<enter-a-file-path>";

    @Test
    public void doit() {
        File file1 = new File(FILE_ONE);
        File file2 = new File(FILE_TWO);
        MultiPart entity = new FormDataMultiPart();
        FileDataBodyPart filePart = new FileDataBodyPart("file", file1);
        entity.bodyPart(filePart);
        filePart = new FileDataBodyPart("file", file2);
        entity.bodyPart(filePart);

        ClientResponse response = resource().path("service")
                .type(MediaType.MULTIPART_FORM_DATA_TYPE)
                .post(ClientResponse.class, entity);
        assertEquals(200, response.getStatus());
        assertEquals("Upload OK", response.getEntity(String.class));
        response.close();
    }
}






更新2(泽西岛2.x)



这是与泽西2.x相同的测试。只需用系统上的一些文件位置替换常量 FILE_ONE FILE_TWO ,然后运行测试。这些文件应保存到当前的工作目录。


UPDATE 2 (Jersey 2.x)

Here is the same test with Jersey 2.x. Just replace the constants FILE_ONE and FILE_TWO with some file locations on your system, and run the test. The files should be saved to your current working directory.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.media.multipart.ContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import org.glassfish.jersey.message.internal.ReaderWriter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;

import org.junit.Test;
import static junit.framework.Assert.assertEquals;

/**
 * Run it like any other JUnit test. Required dependencies are as follows:
 * 
 *  <dependency>
 *     <groupId>org.glassfish.jersey.test-framework.providers</groupId>
 *     <version>2.22.1</version>
 *     <scope>test</scope>
 *  </dependency>
 *     <dependency>
 *     <groupId>org.glassfish.jersey.media</groupId>
 *     <artifactId>jersey-media-multipart</artifactId>
 *     <version>2.22.1</version>
 *     <scope>test</scope>
 *  </dependency>
 * 
 */
public class Jersey2MultipartTest extends JerseyTest {

    @Path("service")
    public static class Service {

        @POST
        @Consumes(MediaType.MULTIPART_FORM_DATA)
        @Produces(MediaType.TEXT_PLAIN)
        public String getTest(@FormDataParam("file") List<FormDataBodyPart> files) {
            for (FormDataBodyPart filePart: files) {
                ContentDisposition cd = filePart.getContentDisposition();
                try (FileOutputStream out = new FileOutputStream(cd.getFileName())) {
                    ReaderWriter.writeTo(filePart.getEntityAs(InputStream.class), out);
                } catch (IOException ex) {
                    ex.printStackTrace(System.out);
                    return "Oops";
                }
            }
            return "Upload OK";
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(Service.class)
                .register(MultiPartFeature.class);
    }

    @Override
    public void configureClient(ClientConfig config) {
        config.register(MultiPartFeature.class);
    }

    private static final String FILE_ONE = "<enter-file-location>";
    private static final String FILE_TWO = "<enter-file-location>";

    @Test
    public void doit() {
        MultiPart entity = new FormDataMultiPart();
        addFiles(entity, FILE_ONE, FILE_TWO);

        Response response = target("service").request()
                .post(Entity.entity(entity, MediaType.MULTIPART_FORM_DATA));
        assertEquals(200, response.getStatus());
        assertEquals("Upload OK", response.readEntity(String.class));
        response.close();
    }

    private void addFiles(MultiPart entity, String... files) {
        for (String file: files) {
            FileDataBodyPart filePart = new FileDataBodyPart("file", new File(file));
            entity.bodyPart(filePart);
        }
    }
}

这篇关于使用Jersey发送多个文件:找不到multipart / form-data的MessageBodyWriter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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