Как получить смешанный составной ответ в ответе RESTEasy?

Я пытаюсь использовать resteasy. Хотя я могу отправить смешанный составной запрос в качестве запроса к веб-службе, я не могу получить смешанный составной ответ в ответ. Например: запрос файла (byte[] или stream) и имени файла в одном ответе. Вот что я тестировал:

Код услуги:

@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 объекта из ответа?

ОБНОВЛЕНИЕ:

Пробовал следующий подход для извлечения разных частей - используйте «границу», чтобы разбить 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. Приведенная выше логика работает. Но получил еще один блок при получении ОТВЕТА от веб-сервиса. Я не смог найти никаких ссылок на решение таких проблем в ответе. Логика предполагает, что для типа детали существует ОДНА деталь. Если в ответе есть, скажем, 2 части JSON, будет сложно определить, какая часть какая. Другими словами, хотя мы можем добавить часть с именем ключа при создании ответа, мы не можем извлечь имена ключей на стороне клиента. Любые подсказки?


person GSai    schedule 05.09.2013    source источник


Ответы (1)


Вы можете попробовать следующий подход...

На стороне сервера...

  1. Создайте объект-оболочку, который может инкапсулировать все типы. Например, у него может быть карта для ТЕКСТА и другая карта для двоичных данных.
  2. Преобразуйте содержимое TEXT в байты (поток октетов).
  3. Создайте метаданные, которые содержат ссылки на имена ключей и их тип. Например, STR_MYKEY1, BYTES_MYKEY2. Эти метаданные также могут быть преобразованы в поток октетов.
  4. Добавьте метаданные и обернутый объект как части составного ответа.

На стороне клиента...

  1. Прочтите метаданные, чтобы получить имена ключей.

  2. Используйте ключевое имя для интерпретации каждой части. Поскольку имя ключа из метаданных сообщает, являются ли исходные данные ТЕКСТОМ или ДВОИЧНЫМИ, вы должны иметь возможность извлечь фактическое содержимое с помощью соответствующей логики.

Тот же подход можно использовать для восходящего потока, от клиента к сервису. Кроме того, вы можете сжимать данные TEXT, что поможет уменьшить размер контента...

person Ganesh K Thiagarajan    schedule 10.04.2014