如何在RESTEasy响应中获得混合多部分?

时间:2013-09-05 13:40:22

标签: resteasy multipart-mixed-replace

我正在尝试使用resteasy。虽然我能够将混合多部分作为请求发送到Web服务,但我无法在响应中获得混合的多部分。 例如:在单个Response中请求文件(byte []或流)和文件名。 以下是我测试的内容:

服务代码:

@Path("/myfiles")
public class MyMultiPartWebService {

@POST
@Path("/filedetail")
@Consumes("multipart/form-data")
@Produces("multipart/mixed")
public MultipartOutput fileDetail(MultipartFormDataInput input) throws IOException {
       MultipartOutput multipartOutput = new MultipartOutput();
       //some logic based on input to locate a file(s)
       File myFile = new File("samplefile.pdf");
       multipartOutput.addPart("fileName:"+ myFile.getName(), MediaType.TEXT_PLAIN_TYPE);
       multipartOutput.addPart(file, MediaType.APPLICATION_OCTET_STREAM_TYPE);
       return multipartOutput;
 }
}

客户代码:

public void getFileDetails(/*input params*/){
    HttpClient client = new DefaultHttpClient();
    HttpPost postRequest = new HttpPost("urlString");
    MultipartEntity multiPartEntity = new MultipartEntity();
    //prepare the request details        
    postRequest.setEntity(multiPartEntity);

    HttpResponse response = client.execute(postRequest);
    HttpEntity returnEntity = response.getEntity();

    //extracting data from the response
    Header header = returnEntity.getContentType();
    InputStream is = returnEntity.getContent();
    if (is != null) {
        byte[] bytes = IOUtils.toByteArray(is);
        //Can we see the 2 parts that were added?
        //Able to get a single InputStream only, and hence unable to differentiate two objects in the response
        //Trying to see the contents - printing as string
        System.out.println("Output from Response :: " + new String(bytes));
     }
 }

输出如下 - 能够看到具有不同内容类型的2个不同对象,但无法单独提取它们。

Output from Response :: 
--af481055-4e4f-4860-9c0b-bb636d86d639
Content-Type: text/plain

fileName: samplefile.pdf
--af481055-4e4f-4860-9c0b-bb636d86d639
Content-Length: 1928
Content-Type: application/octet-stream

%PDF-1.4
<<pdf content printed as junk chars>>

如何从响应中提取2个对象?

更新:

尝试了以下方法来提取不同的部分 - 使用'boundary'来打破MultipartStream;使用内容类型字符串来提取approp对象。

    private void getResponeObject(HttpResponse response) throws IllegalStateException, IOException {
        HttpEntity returnEntity = response.getEntity();
        Header header = returnEntity.getContentType();
        String boundary = header.getValue();
        boundary = boundary.substring("multipart/mixed; boundary=".length(), boundary.length());
        System.out.println("Boundary" + boundary); // --af481055-4e4f-4860-9c0b-bb636d86d639
        InputStream is = returnEntity.getContent();
        splitter(is, boundary);
    }

    //extract subsets from the input stream based on content type
    private void splitter(InputStream is, String boundary) throws IOException {
        ByteArrayOutputStream boas = null;
        FileOutputStream fos = null;

        MultipartStream multipartStream = new MultipartStream(is, boundary.getBytes());
        boolean nextPart = multipartStream.skipPreamble();
        System.out.println("NEXT PART :: " + nextPart);
        while (nextPart) {
            String header = multipartStream.readHeaders();
            if (header.contains("Content-Type: "+MediaType.APPLICATION_OCTET_STREAM_TYPE)) {
                fos = new FileOutputStream(new File("myfilename.pdf"));
                multipartStream.readBodyData(fos);
            } else if (header.contains("Content-Type: "+MediaType.TEXT_PLAIN_TYPE)) {
                boas = new ByteArrayOutputStream();
                multipartStream.readBodyData(boas);
                String newString = new String( boas.toByteArray());
            } else if (header.contains("Content-Type: "+ MediaType.APPLICATION_JSON_TYPE)) {
                //extract string and create JSONObject from it
            } else if (header.contains("Content-Type: "+MediaType.APPLICATION_XML_TYPE)) {
                //extract string and create XML object from it
            }
            nextPart = multipartStream.readBoundary();
        }
    }

这是正确的做法吗?

更新2: 上面的逻辑似乎有效。但是当从webservice接收到RESPONSE时,又得到了另一个块。我找不到任何在Response中处理此类问题的引用。 该逻辑假设零件类型有一个零件。如果响应中有2个JSON部分,则很难确定哪个部分是什么。换句话说,虽然我们可以在创建响应时添加具有键名的部分,但我们无法在客户端提取键名。 有线索吗?

1 个答案:

答案 0 :(得分:1)

您可以尝试以下方法......

在服务器端......

  1. 创建一个可以封装所有类型的包装器对象。例如,它可以有一个Map for TEXT和另一个Map for Binary data。
  2. 将TEXT内容转换为字节(八位字节流)。
  3. 创建一个MetaData,其中包含对Key名称及其类型的引用。例如,STR_MYKEY1,BYTES_MYKEY2。此元数据也可以转换为八位字节流。
  4. 将元数据和包装的实体添加为多部分响应的部分。
  5. 在客户端......

    1. 阅读MetaData以获取密钥名称。

    2. 使用键名来解释每个部分。由于元数据中的Keyname告诉原始数据是TEXT还是BINARY,因此您应该能够使用适当的逻辑提取实际内容。

    3. 从客户端到服务,上游可以使用相同的方法。 最重要的是,您可以压缩TEXT数据,这将有助于减少内容大小...