【问题标题】:CXF "No Message body reader found" for byte array parameter in POST servicePOST 服务中字节数组参数的 CXF“未找到消息正文阅读器”
【发布时间】:2014-11-06 16:09:38
【问题描述】:

我正在尝试编写一个服务,该服务将通过将文件作为 POST 实体中的字节数组来负责上传文件。这是我的代码

我的 CXF 服务

@Path("MyTest")
public class TestService {
    @POST
    public String MyPost(Byte[] bytes){
        System.out.println("Service invoked");
        return "Hello, I am a POST response";
    }
}

我的客户

File image = new File("C:\\snake.jpg");
FileInputStream is = new FileInputStream(image);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] fileInBytes = bos.toByteArray();

Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/MyApp");
target = target.path("MyTest");
Response response = target.request().post(Entity.entity(fileInBytes, MediaType.APPLICATION_OCTET_STREAM));

InputStream i = (InputStream) response.getEntity();
BufferedReader br = new BufferedReader(new InputStreamReader(i));
System.out.println(br.readLine());

这是我得到的错误

SEVERE: No message body reader has been found for class [Ljava.lang.Byte;, ContentType: application/octet-stream
Nov 06, 2014 4:02:50 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.WebApplicationException: HTTP 415 Unsupported Media Type
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1298)
...

有什么想法吗?有没有更好的文件上传服务方式?

谢谢

【问题讨论】:

    标签: java web-services cxf jax-rs


    【解决方案1】:

    您可以使用InputStream

    @POST
    public String MyPost(InputStream is) throws IOException  {
        BufferedImage image = ImageIO.read(is);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(image)));
        System.out.println("Service invoked");
        return "Hello, I am a POST response";
    }
    

    除此之外,在您的客户端代码中,您实际上并没有向输出流写入任何内容。它应该更像

    FileInputStream is = new FileInputStream(image);
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    
    int nRead;
    byte[] data = new byte[16384];
    while ((nRead = is.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, nRead);
    }
    buffer.flush();
    byte[] fileInBytes = buffer.toByteArray();
    
    Response response = target.request().post(Entity.entity(fileInBytes, 
            MediaType.APPLICATION_OCTET_STREAM));
    

    更新

    可以实际使用字节数组。你只需要使用原语byte[]

    @POST
    public String MyPost(byte[] bytes) throws IOException  {
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bytes)));
        System.out.println("Service invoked");
        return "Hello, I am a POST response";
    }
    

    甚至还可以使用File

    @POST
    public String MyPost(File file) throws IOException  {
        BufferedImage image = ImageIO.read(file);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(image)));
        System.out.println("Service invoked");
        return "Hello, I am a POST response";
    }
    

    JAX-RS 在磁盘上创建一个用于输入的临时文件。它从网络缓冲区中读取数据并将读取的字节保存到这个临时文件中。

    它们都有效。选择你的毒药

    【讨论】:

      【解决方案2】:

      遇到了完全相同的问题。将 application/octet-stream 作为参数添加到 @Consumes 注释解决了这个问题:

      @POST
      @Consumes({"application/octet-stream", "text/xml", "application/xml"})
      @Produces({"text/xml", "application/xml"})
      public Object post(String xmlData) throws Exception {
          ...
      }
      

      但是,如果您可以确保调用者在 HTTP 请求标头中设置了适当的 Content-Type,则可能不需要在 @Consumes 注释中添加“application/octet-stream”。

      使用 CURL 的示例:

      curl -vX POST -H "Content-Type:text/xml" -T "postdata.xml" "http://localhost:9000/ws/rest/..."

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-05
        • 2015-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多